Android - 如何让 recyclerview ListAdpater 停止闪烁?

时间:2021-02-25 17:58:53

标签: android android-recyclerview kotlin-flow android-listadapter

我有一个回收器视图,其适配器使用 ListAdapter(1.1.0 版):

class InnerEpisodeFragmentAdapter(
    private val actCtx: Context,
) : ListAdapter<Episode, InnerEpisodeFragmentAdapter.MViewHolder>(COMPARATOR) {
...

recycler 视图由来自 Room 数据库 Episode 表的 kotlin 流提供:

vm.episodesFlow().asLiveData().observe(viewLifecycleOwner) { episodes ->
  episodes.let { adapter.submitList(it) }
}

@Query("SELECT * FROM Episode ORDER BY pubDate DESC")
fun episodesFlow(): Flow<List<Episode>>

除此之外,每次剧集表中的元组更改时,都会发出新的剧集列表并更新回收器视图。

它工作正常,但每次更新时都会出现可怕的 BLINK。它会给用户带来糟糕的体验。

当流发出新值时如何避免这种闪烁?

在我的应用程序的先前版本中,我使用了诸如 notifyDataSetChanged() 或 notifyItemChanged() 之类的函数,它们从不闪烁。我知道我仍然可以尝试使用这些函数,但如果我无法避免闪烁时我会非常失望使用 kotlin 流程,如上所示。谢谢。

2 个答案:

答案 0 :(得分:3)

比较者

areItemsThesame() 被错误地实现。您正在比较的是旧对象和 newObject 可能不是相同对象的引用。相反,您有些人使用某种 uuid 来比较两者,例如主键。如果对象不同,它将返回 false,因此永远不会调用 areContentsTheSame,否则如果对象相同,则因为 oldObject 和 newObject 都指向相同的引用,所以它们没有比较内容的意义。

抱歉,我是从 Mobile 写的错误

答案 1 :(得分:0)

======== 要求的附加信息 ======

我的比较器很好,完全符合我的要求。 例如,我希望在每个回收者视图项中实时更新 isPlayed。确实如此。但是整个列表一闪而过。回收站视图消失了几分之一秒,然后以更新的信息重新出现。

companion object {
    private val COMPARATOR = object : DiffUtil.ItemCallback<Episode>() {
        override fun areItemsTheSame(oldItem: Episode, newItem: Episode): Boolean {
            return oldItem === newItem
        }

        override fun areContentsTheSame(oldItem: Episode, newItem: Episode): Boolean {
            return (oldItem.id == newItem.id)
                    && (oldItem.isOnDisk == newItem.isOnDisk)
                    && (oldItem.downloadId == newItem.downloadId)
                    && (oldItem.isPlayed == newItem.isPlayed)
                    && (oldItem.isDeleted == newItem.isDeleted)
        }
    }
}