动画后查看项目重叠

时间:2018-07-11 18:54:05

标签: android android-recyclerview

我有一个RecyclerView设置,并且遇到了一个非常奇怪的问题,即在某些适配器更新期间,RecyclerView的各项相互重叠,好像它们在动画的中间停止了动画一样。此问题似乎主要发生在移动项目时,但有时删除具有相同的效果。我的初始设置是将AndroidX beta01 ListAdapter和Room用于我的应用程序数据库。我将简单地观察LiveData并在observe方法中调用submitList()

我还应该注意,我添加了一个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方法。

编辑:应注意的是,由于我的应用程序的工作方式,收件箱中的项目需要移至新位置并进行更新。因此,调用notifyItemMovednotifyItemChanged

可能存在一些问题

1 个答案:

答案 0 :(得分:2)

奇怪的是,发现这是共享元素转换的问题。显然,过渡在某种程度上导致了recyclerview的动画不正确,在删除了共享元素后,所有功能均按预期运行。