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}"
/>
这会奏效。如果没有,那么您可能需要使用自定义绑定适配器。
我有一个显示数据列表的回收视图。它的行和页脚具有正常内容。我在我的代码中没有看到任何错误,但是当我尝试构建项目时,我收到以下错误。我试图清除缓存并使我的 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}"
/>
这会奏效。如果没有,那么您可能需要使用自定义绑定适配器。