android - 如何正确编写 DiffUtil.Callback 以便 recyclerview 移动动画?
问题描述
我有一个普通旧数据类型的 recyclerview 适配器,在我的例子中是 char。
适配器由列表支持。
setChar 方法更新列表。
假设在我的情况下,setChar 仅使用与适配器相同的列表调用,但仅使用移动的项目。
fun setChar(list: List<Char>) {
val diffResult = DiffUtil.calculateDiff(CharDiffCallBack(mChars, list), true)
mChars = list
diffResult.dispatchUpdatesTo(this)
}
class CharDiffCallBack(private val mOldList: List<Char>, private val mNewList: List<Char>) :
DiffUtil.Callback() {
override fun getOldListSize() = mOldList.size
override fun getNewListSize() = mNewList.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = mOldList[oldItemPosition] == mNewList[newItemPosition]
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = false
}
DiffUtil.Callback 的正确实现是什么,以便将动作正确地设置为 recyclerview 的动作?
目前,它的动画效果就好像该项目被移除并重新插入一样。
解决方案
在我看来,你同时犯了两个错误。
第一个(不确定是否是错误,但通常是相反的方式):您false
从areContentsTheSame
方法返回。它强制RecyclerView
重新绑定视图。如果只是项目的顺序发生了变化,则不是这种方式,只有在false
需要重新绑定视图时才返回。所以如果item的内容没有变化,就true
默认返回。
第二个嫌疑人是你的setChar
方法。似乎DiffCallback
一直需要两个相等的列表。如果您在活动/片段中有数据列表并传递相同List
的数据以设置新数据,那么这就是迫使DiffCallback
工作不正确的事情,因为DiffCallback
在您的列表中看不到任何位置变化,因为它们都是相等的。
我刚刚测试过,只有这两者的结合才能得到你的结果。所以你应该怎么做:
class YourAdapter(..., charList: List<Char>, ...): RecyclerView.Adapter<...>() {
private val mChars = ArrayList(charList)
// You have to keep a different List object (so, a copy) of the one you pass from the activity
...
fun setChar(list: List<Char>) {
val diffResult = DiffUtil.calculateDiff(CharDiffCallBack(mChars, list), true)
mChars.clear()
mChars.addAll(list)
diffResult.dispatchUpdatesTo(this)
}
}
class CharDiffCallBack(private val mOldList: List<Char>, private val mNewList: List<Char>) :
DiffUtil.Callback() {
...
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = true
}
这种方式DiffCallback
总是需要两个不同的列表,一个是旧的,一个是更新的数据。另外,true
从areContentsTheSame
方法返回
推荐阅读
- python - 未定义符号:THPVariableClaload_textures.cpython-37m-x86_64-linux-gnu.so:未定义符号:THPVariableClass
- c# - 在 GitHub Actions 中执行 Windows 应用程序(错误:无法识别工具版本“15.0”)
- javascript - 使用 React 创建 Twilio 令牌的 Firebase 可调用函数
- amazon-web-services - 我可以为 Istio 预置的经典 AWS ELB 定义子域吗?
- python - 使用 scipy 的相关性
- javascript - 加载图像时反应显示页面
- c - 如何在 Clion 上运行多个 C 代码?
- python - ValueError:压缩距离矩阵必须仅包含有限值
- c - 读取特定大小的流,小于文件大小 (C)
- r - R中是否有与Stata的PSACALC等价的东西?