android - 动画后 RecyclerView 项目重叠
问题描述
我有一个 RecyclerView 设置,我遇到了一个非常奇怪的问题,在某些适配器更新期间,RecyclerView 的项目相互重叠,就好像它们在动画中间停止动画一样。此问题似乎主要发生在移动项目时,但有时删除具有相同的效果。我最初的设置是使用AndroidX
beta01ListAdapter
和 Room 作为我的应用程序数据库。我会简单地观察LiveData
我会调用的观察方法内部的 andsubmitList()
我还应该注意,我添加了一个 RecyclerView.AdapterDataObserver 扩展onItemMoved
并调用layoutManager.moveToPosition(0)
以确保用户看到更新。
从那以后,我尝试了许多故障排除步骤,其中包括:
- 摆脱稳定的 ID
- 为适配器差异编写我自己的逻辑(我扩展了 RecyclerView.Adapter),并将使用以下代码手动查找列表差异:
- 我注释掉了
moveToPosition(0)
代码 - 我覆盖了 AdapterDataObserver 中的所有方法,以确保执行正确的操作;他们是
手动列表差异方法:
private fun calculateListDiffs(model: List<T>) {
when {
model.size > list.size -> {
var i = 0
while (i < itemCount) {
if (!areItemsSame(list[i], model[i])) {
list.add(i, model[i])
notifyItemInserted(i)
} else
i++
}
}
model.size < list.size -> {
var i = 0
while (i < itemCount) {
when {
i >= model.size && !areItemsSame(list[i], model[model.size - 1]) -> {
list.removeAt(i)
notifyItemRemoved(i)
}
i < model.size && !areItemsSame(list[i], model[i]) -> {
list.removeAt(i)
notifyItemRemoved(i)
}
else -> i++
}
}
}
else -> {
run loop@{
for (i in 0 until itemCount) {
when {
!areItemsSame(list[i], model[i]) -> {
val pivot = model[i]
for (j in i until itemCount) {
if (areItemsSame(list[j], pivot)) {
list.removeAt(j)
list.add(i, pivot)
notifyItemMoved(j, i)
notifyItemChanged(i)
return@loop
}
}
}
!areContentsSame(list[i], model[i]) -> {
list[i] = model[i]
notifyItemChanged(i)
}
}
}
}
}
}
}
问题仍然存在,经过所有这些测试,这似乎是适配器动画固有的问题,而不是 ListAdapter 或我自己的 diff 方法。
编辑:应该注意,由于我的应用程序的工作方式,收件箱中的项目需要移动到新位置并进行更新。所以也许打电话notifyItemMoved
和notifyItemChanged
解决方案
来发现,奇怪的是,这是共享元素转换的问题。显然,在删除共享元素后,转换以某种方式导致 recyclerview 无法正确设置动画,一切都按预期运行。
推荐阅读
- cmake - cmake -D CMAKE_CXX_FLAGS="-march=armv8-a" 用于 aarch64 编译
- mysql - 事务期间的表锁包含 max()
- scala - 如何截断火花数据框列的值?
- regex - 使用 spark scala 的数据帧中 json 字符串的正则表达式
- c - ioctl“无法发送 spi 消息:无效参数”Beaglebone Black
- java - 无法使用 BufferedReader 读取文件
- google-apps-script - 在 google sheet 自定义脚本函数中解析数据时出错
- r - 如何通过传递两个变量来创建数据帧的多个子集
- java - 如何获取变量的类
- php - 如何使用正则表达式在 sql 中搜索包含 # 标签的记录,但忽略 #FFFFFF 或 html 标签内的任何其他颜色