【问题标题】:RecyclerView ListAdapter does not update list correctlyRecyclerView ListAdapter 没有正确更新列表
【发布时间】:2018-11-27 16:19:58
【问题描述】:

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

问题是当用户按下 Checkbox 时,Task 对象会更新为已完成,数据库会反映此更改,但 有时适配器 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,因此没有要更新的差异。

我是否缺少任何实现?

【问题讨论】:

  • 大家在这里找到解决方案了吗?我可能会遇到类似的问题。
  • @Bink,不,我找不到解决方案。我调试了几次,用 LiveData 替换了 Rx,在 DiffUtil.ItemCallback 中尝试了不同的方法,但没有成功。
  • 我认为错误是AsyncListDiffer#submitList评估newList == mList,如果你只是更改一个项目,而不是列表的(大小),则此语句为true并取消更新过程.但我还没有找到解决方法。

标签: android android-recyclerview rx-java android-adapter android-room


【解决方案1】:

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

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

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

【讨论】:

  • 您好!感谢您的回复。但由于我使用的是数据类,按照我的做法进行比较,如果任何属性不同,它将返回 false。所以,我看不出我的方法和你的方法有很大的不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-26
  • 2018-09-18
  • 2019-09-21
  • 1970-01-01
  • 2021-06-10
  • 2020-09-14
  • 2018-08-25
相关资源
最近更新 更多