Android 数据绑定不会在 RecyclerView 中生成有界视图

Android data binding doesn't generate a bounded view in RecyclerView

我有一个显示数据列表的回收视图。它的行和页脚具有正常内容。我在我的代码中没有看到任何错误,但是当我尝试构建项目时,我收到以下错误。我试图清除缓存并使我的 Android Studio 无效,但没有成功。我仍然在控制台中收到类似的错误。

> Task :app:kaptDebugKotlin
/home/hesam/apps/projects/atco/rumi-android/app/build/generated/source/kapt/debug/com/atco/rumi/DataBinderMapperImpl.java:15: error: cannot find symbol
import com.atco.rumi.databinding.RowAboutItemBindingImpl;
                                ^
  symbol:   class RowAboutItemBindingImpl
  location: package com.atco.rumi.databinding
> Task :app:kaptDebugKotlin FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:kaptDebugKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
   > java.lang.reflect.InvocationTargetException (no error message)

我花了几个小时找出问题所在,但我做不到。编译器有问题吗?

我的 app/build.gradle 文件中确实启用了数据绑定。

...
   dataBinding {
        enabled = true
    }
...

这是我的适配器class:

import android.content.Context
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.atco.rumi.BuildConfig
import com.atco.rumi.databinding.RowAboutFooterBinding
import com.atco.rumi.databinding.RowAboutItemBinding

data class AboutItem(
    val title: String,
    val icon: Drawable?,
    val webUrl: String
)

data class AboutFooter(
    val version: String
)

class AboutAdapter(
    val context: Context
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private val items: List<AboutItem> = getAboutItems(context)

    companion object {
        const val TYPE_HEADER = 0
        const val TYPE_FOOTER = 1
        const val TYPE_ITEM = 2
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        return when (viewType) {
            TYPE_ITEM -> {
                val binding = RowAboutItemBinding.inflate(inflater)
                ItemViewHolder(binding)
            }
            TYPE_FOOTER -> {
                val binding = RowAboutFooterBinding.inflate(inflater)
                FooterViewHolder(binding)
            }
            else -> throw IllegalArgumentException("Invalid view type")
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is FooterViewHolder -> {
                val version = getFormattedVersion(context, BuildConfig.VERSION_NAME)
                val item = AboutFooter(version)
                holder.bindItem(item)
            }
            is ItemViewHolder -> holder.bindItem(items[position], position)
            else -> throw IllegalArgumentException()
        }
    }

    override fun getItemCount(): Int {
        return items.size + 1 // Because we need to append the Footer
    }

    override fun getItemViewType(position: Int): Int {
        if (position == 0 && items.isEmpty()) return TYPE_FOOTER
        if (position == items.size) return TYPE_FOOTER
        return TYPE_ITEM
    }

    inner class ItemViewHolder(val binding: RowAboutItemBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bindItem(item: AboutItem, position: Int) {
            binding.item = item
            binding.aboutItemContainer.setOnClickListener {
                // TODO: Implement it
            }
            binding.executePendingBindings()
        }
    }

    inner class FooterViewHolder(val binding: RowAboutFooterBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bindItem(item: AboutFooter) {
            binding.item = item
            binding.executePendingBindings()
        }
    }
}

这是我的 row_about_item.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="item"
            type="com.atco.rumi.scenes.tabs.about.AboutItem" />
    </data>

    <LinearLayout
        android:id="@+id/aboutItemContainer"
        style="@style/about_action_click">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="30dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="30dp"
            app:srcCompat="@{item.icon}" />

        <TextView
            android:id="@+id/textView"
            style="@style/about_textView"
            android:text="@{item.title}"
            tools:text="This is the title" />

    </LinearLayout>
</layout>

最后,这是我的 row_about_footer.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="item"
            type="com.atco.rumi.scenes.tabs.about.AboutFooter" />
    </data>

    <LinearLayout style="@style/about_action_click">

        <TextView
            android:id="@+id/textView"
            style="@style/about_textView_footer"
            android:layout_marginStart="60dp"
            android:text="@{item.version}"
            tools:text="Version 1.0" />

    </LinearLayout>
</layout>

嫌疑人是 srcCompat=@{item.icon},因为我不确定为 srcCompat(如果有的话)究竟生成了什么数据绑定。所以我相信如果你把它改成

<ImageView
        ...
        android:src="@{item.icon}"
/>

这会奏效。如果没有,那么您可能需要使用自定义绑定适配器。