RecyclerView ListAdapter 未正确更新列表

Igo*_*dro 6 android android-adapter rx-java android-recyclerview android-room

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

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

任务列表片段

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

任务道

@Query("SELECT * FROM task")
fun getAllTasks(): Flowable<MutableList<Task>>
Run Code Online (Sandbox Code Playgroud)

任务列表适配器

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
}
Run Code Online (Sandbox Code Playgroud)

任务

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
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

调试应用程序,有时isCompleted现场正确更新和有时领域就是把差异期间已经更新,所以说,鉴于没有更新。我找不到这个问题的任何模式。就我而言,有时视图会holder.viewStrike改变其可见性,有时会保持不一致的状态。

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

我错过了任何实现吗?

set*_*ari 0

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

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

但是没有必要比较永远不会改变的值,例如:id