我正在使用RecyclerView
来显示从数据库中检索为Java对象的项目列表。对象中的一个字段是数据库中项目的ID,因此可以使用它执行进一步的操作。我的areContentsTheSame
实现会比较对象中的各个字段,以确定项目的内容是否已更改。
问题在于,有时在刷新数据源时,项目的ID会在没有可见内容更改的情况下发生更改(即,相同的项目将从数据库中删除,然后再次添加,在此过程中更改其ID)。在这种情况下,我当前的areContentsTheSame
实现返回true
。但是当areContentsTheSame
返回true
时,RecyclerView
视图不会重新绑定(onBindViewHolder
不会为areContentsTheSame
返回true
的项目调用areContentsTheSame
}),因此视图仍然包含对包含旧ID的旧对象的引用,因此在尝试对该项执行某些操作时会导致错误(例如用户点击它以显示它)。
我尝试在ID更改时使false
返回areContentsTheSame
,即使没有发生可见的更改,也会强制重新绑定视图,但这会导致“项目已更改”动画显示即使该项目没有明显改变。我想要的是一种强制视图重新绑定而不false
返回areContentsTheSame
或true
返回<asp:Image ID="Image1" runat="server" ImageUrl="~/images/" />
并触发重新绑定的方法没有显示动画。
答案 0 :(得分:4)
实现目标的最佳方法是覆盖DiffUtil.Callback
实施中的getChangePayload()
方法。
当
areItemsTheSame(int, int)
为两个项目返回true
而areContentsTheSame(int, int)
为其返回false
时,DiffUtil
会调用此方法获取有关更改的有效负载。< / p>例如,如果您将
DiffUtil
与RecyclerView
一起使用,则可以返回项目中已更改的特定字段,而ItemAnimator
可以使用该信息运行正确的动画。默认实现返回
null
。
因此,请确保在数据库ID更改时,areContentsTheSame()
方法返回false
,然后实现getChangePayload()
以检查此情况并返回非空值。也许是这样的:
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
if (onlyDatabaseIdChanged(oldItemPosition, newItemPosition)) {
return Boolean.FALSE;
} else {
return null;
}
}
从此方法返回的对象并不重要,只要在您不想看到默认更改动画的情况下它不为空。
有关为什么的详细信息,请参阅此问题的答案:https://stackoverflow.com/a/47355363/8298909
答案 1 :(得分:0)
大多数答案找出了DiffUtil的一些基本示例,其中 代码看起来像
class MyDiffUtil( private val oldList: List<Item>, private val newList:
List<Item> ) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size
override fun getNewListSize(): Int = newList.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].id == newList[newItemPosition].id
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].id == newList[newItemPosition].id
}
}
当新项目添加或删除具有列表ID的项目时,上述代码中的将正常工作。但是当id保持不变但更改了一些其他内容时,适配器就不会更新,因为这种和平的代码
return oldList[oldItemPosition].id == newList[newItemPosition].id
在这里,我们检查了id而不是其他项目,因此您只需删除id并编写此新代码
class MyDiffUtil( private val oldList: List<Item>, private val newList:
List<Item> ) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size
override fun getNewListSize(): Int = newList.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
}