android - 与 RecyclerView 的数据绑定未正确呈现
问题描述
我正在尝试将数据绑定与 RecyclerView 一起使用。我设置了一个简单的应用程序,它在 RecyclerView 中显示数字 1 到 50,每行一个。我想对每一行使用数据绑定。
这是我的适配器的代码(请注意,我调用了dataBinding.executePendingBindings()
):
class SimpleAdapter
: ListAdapter<Int, SimpleAdapter.SimpleAdapterViewHolder>(SimpleAdapterDiffUtil()) {
inner class SimpleAdapterViewHolder(
private val dataBinding: SimpleAdapterViewHolderBinding
) : RecyclerView.ViewHolder(dataBinding.root) {
fun bind(str: String) {
Log.e("MYTAG", "setting TextView: $str")
dataBinding.txtView.text = str
dataBinding.executePendingBindings()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SimpleAdapterViewHolder {
val binding = SimpleAdapterViewHolderBinding.inflate(
LayoutInflater.from(parent.context), parent, false)
return SimpleAdapterViewHolder(binding)
}
override fun onBindViewHolder(holder: SimpleAdapterViewHolder, position: Int) {
val stringValue = getItem(position)
holder.bind(stringValue.toString())
}
}
private class SimpleAdapterDiffUtil: DiffUtil.ItemCallback<Int>() {
override fun areItemsTheSame(oldItem: Int, newItem: Int): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: Int, newItem: Int): Boolean {
return oldItem == newItem
}
}
这是视图 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">
<data>
<variable
name="text"
type="String" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txt_view"
android:text="@{text}"
android:layout_width="match_parent"
android:layout_height="36dp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black"
app:layout_constraintTop_toBottomOf="@id/txt_view"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
这就是它的作用:
如您所见,在初始屏幕中,没有任何行未正确呈现。当我向下滚动时,我发现它从第 23 行开始渲染。然后,如果我向上滚动,我终于可以看到前面的行被填充了。
如果我将代码更改为使用普通的旧视图,而不是数据绑定,它会按预期工作。代码在这里:
// This works fine!
class SimpleAdapter
: ListAdapter<Int, SimpleAdapter.SimpleAdapterViewHolder>(SimpleAdapterDiffUtil()) {
inner class SimpleAdapterViewHolder(
private val rootView: View
) : RecyclerView.ViewHolder(rootView) {
fun bind(str: String) {
Log.e("MYTAG", "setting TextView: $str")
rootView.findViewById<TextView>(R.id.txt_view).text = str
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SimpleAdapterViewHolder {
val rootView = LayoutInflater.from(parent.context)
.inflate(R.layout.simple_adapter_view_holder, parent, false)
return SimpleAdapterViewHolder(rootView)
}
override fun onBindViewHolder(holder: SimpleAdapterViewHolder, position: Int) {
val stringValue = getItem(position)
holder.bind(stringValue.toString())
}
}
private class SimpleAdapterDiffUtil: DiffUtil.ItemCallback<Int>() {
override fun areItemsTheSame(oldItem: Int, newItem: Int): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: Int, newItem: Int): Boolean {
return oldItem == newItem
}
}
解决方案
正如我在您的 xml 中看到的,您正在设置android: text="@{text}"
换句话说,textView 值是从binding.text
您设置dataBinding.txtView.text = str
的,它将更新文本。之后使用executePendingDataBinding
它的值将被重置为 null 或空的dataBinding.text
(aka )。android: text="@{text}"
所以你应该设置
dataBinding.text = str
代替
dataBinding.txtView.text = str
推荐阅读
- excel - Do While 循环运行时错误 1004 在第二次通过
- jquery - 如何在锚标记的href值中附加当前窗口位置
- ios - 线程 1:在获取 TableView 的可重用单元格时发出 SIGABRT 信号
- java - 从弹出菜单中捕获鼠标 XY 位置
- flutter - 在 ListView.builder 上多次使用相同的索引
- asp.net - 无法在 Asp.NET CORE 中将我的环境变量设置为开发
- r - Prophet 模型中假期的巨大不确定性
- python - 如何在 tensorflow DataSet 的每次迭代中添加随机性?
- javascript - 使用字符串和数字访问函数?
- ios - 这种时间戳是什么,如何将其转换为人类可读的日期?