2

在我的 RecyclewView 的适配器中,我使用 DiffUtils 仅更新那些被修改的项目。在执行此操作时,我注意到 ImageViews 在每次更新时都会闪烁,并且在调试时我发现 onCreateViewHolder每次更新数据时都会调用适配器的方法,因此不会像应有的那样重用视图持有者。当我摆脱 DiffUtil 并使用简单的notifyDataSetChanged闪烁消失时。那么为什么要重新创建那些 ViewHolders,我该如何解决呢?

这是我的 DiffUtil 回调:

class MyDiffUtilCallback(val newList: List<Item>, val oldList: List<Item>) : DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
    return newList[newItemPosition].id == oldList[oldItemPosition].id
}

override fun getOldListSize(): Int = oldList.size

override fun getNewListSize(): Int = newList.size

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
    return newList[newItemPosition] == oldList[oldItemPosition]
}

}

以及我如何更新我的适配器:

fun updateItems(items: List<Item>) {
    val diff = DiffUtil.calculateDiff(MyDiffUtilCallback(items, this.items))
    this.items = items
    diff.dispatchUpdatesTo(this)
}

编辑: 我进一步研究了这个问题,并注意到在使用时也重新创​​建了视图notifyDataSetChanged,我一直认为在更新期间视图被重用,但我想情况并非如此。无论如何,只有在使用 DiffUtil 而不是时,图像闪烁仍然可见notifyDataSetChanged,我不知道为什么

4

1 回答 1

-1

在您的代码中,而不是下面的代码

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): 
Boolean {
    return newList[newItemPosition] == oldList[oldItemPosition]
}

用这个。

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): 
Boolean {
    return newList[newItemPosition].id == oldList[oldItemPosition].id
}

因为当您比较它们通过内存引用比较的两个对象时,我认为在这种情况下,在准备新列表时您没有使用旧列表的相同对象,因此您应该使用自定义数据模型的唯一 ID 检查它们是否相等“物品”。但在你的情况下,它再次调用 onCreateViewHolder,它不应该在这里发生,尝试这种方法一次,顺便说一下,你是否使用支持多种类型项目的适配器,如果是,这可能是可能的,因为在更改列表中你是获取尚未创建的新类型的项目,如果我们在之前的旧列表中没有这些类型的项目。

于 2020-04-11T12:57:21.093 回答