回收器视图列表适配器未正确更新列表



我正在使用Android RoomRx Flowable来更新RecyclerView我的数据库中的对象。为了获得更好的动画和性能,我更新了项目以在我的项目中使用新的 ListAdapter。

问题是当用户按下 Task 对象更新为已完成Checkbox时,数据库会反映此更改,但有时适配器ListAdapter通知我的onBindViewHolder有时它说我的视图已经更新。

任务列表片段

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewModel.loadTasks(onTasksLoaded = { adapter.submitList(it) })
}

任务道

@Query("SELECT * FROM task")
fun getAllTasks(): Flowable<MutableList<Task>>

任务列表适配器

class TaskListAdapter : ListAdapter<Task, BindingHolder<*>>(TaskDiffCallback()) {
override fun onBindViewHolder(holder: BindingHolder<*>, position: Int) {
val task = getItem(position)
// more binding code
// THE ISSUE IS HERE
if (task.completed) {
holder.viewStrike.visibility = View.VISIBLE
} else {
holder.viewStrike.visibility = View.INVISIBLE
}
}
// more adapter code
}

任务

data class Task(
@ColumnInfo(name = "task_is_completed") var completed: Boolean = false,
@ColumnInfo(name = "task_description") var description: String,
@ColumnInfo(name = "task_category_id") var categoryId: Long? = null,
@ColumnInfo(name = "task_due_date") var dueDate: Calendar? = null
) : Parcelable {
@IgnoredOnParcel
@ColumnInfo(name = "task_id")
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}

DiffUtil

class TaskDiffCallback : DiffUtil.ItemCallback<Task>() {
override fun areItemsTheSame(oldItem: Task, newItem: Task) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Task, newItem: Task) =
oldItem.task == newItem.task
}

调试应用程序时,有时isCompleted字段会正确更新,有时该字段在 Diff 期间已经更新,因此它表示视图没有更新。我找不到这个问题的任何模式。就我而言,有时视图holder.viewStrike会更改其可见性,有时它会保持不一致的状态。

该问题似乎与ListAdapter本身有关,该有时会发送带有更新值的oldItem,因此没有要更新的差异。

我是否缺少任何实现?

可能晚了,但我会为其他人写一个答案。 您不应该以这种方式使用 areContentTheSame。 您必须比较与这两个对象相关的值,这两个对象可以更改。 喜欢:

override fun areContentsTheSame(oldItem: Task, newItem: Task){
return if(oldItem.completed == newItem.completed && oldItem.description == newItem.description && oldItem.dueDate == newItem.dueDate)}

但是比较永远无法更改的值是不必要的,例如:

最新更新