我正在使用
RecyclerView
和 ListAdapter
,其中显示 2 种类型的项目:内容和占位符。
在此示例中,初始列表包含 10 个内容项和 10 个占位符项,然后我将其替换为另外 10 个内容项(= 总共 20 个项)。
使用
ListAdapter.submitList(list)
执行此操作可按预期工作并显示正确的更改动画。就像这个 GIF 所示:
但是,当我滚动到屏幕上显示 only 占位符的部分时,
.submitList(list)
会导致不必要的滚动,如以下 GIF 所示:
我的比较逻辑:(应该没问题,通常所有动画都按预期工作)
sealed class MyItem {
data class Content(val text: String) : MyItem()
data class Placeholder(val text: String) : MyItem()
}
class MyDiffCallback : DiffUtil.ItemCallback<MyItem>() {
override fun areItemsTheSame(oldItem: MyItem, newItem: MyItem): Boolean =
oldItem::class == newItem::class && when (oldItem) {
is MyItem.Content -> oldItem.text == (newItem as MyItem.Content).text
is MyItem.Placeholder -> oldItem.text == (newItem as MyItem.Placeholder).text
}
override fun areContentsTheSame(oldItem: MyItem, newItem: MyItem): Boolean =
oldItem == newItem
}
可能出了什么问题?这真的按预期工作吗?我只是错过了一些东西?
RecyclerView.Adapter
并执行以下操作
通过 DiffUtil.calculateDiff(...)
手动比较新列表 - 这有同样的问题(ListAdapter
毕竟在内部使用 DiffUtil
)adapter.notifyItemRangeChanged(...)
来完成解决方法 - 这有效并且不会导致滚动,但我对此解决方法不满意,并且不想将其应用到我的所有功能中在 areContentsTheSame() 中尝试这个
return if(oldItem is MyItem.Placeholder && newItem is MyItem.Content) true
else oldItem == newItem