gpt4 book ai didi

android - 更新 ListAdapter 上的项目后,DiffUtil ItemCallback areContentsTheSame() 始终返回 true

转载 作者:行者123 更新时间:2023-12-02 02:32:22 25 4
gpt4 key购买 nike

在使用 ListAdapter 时,我注意到更新项目后,DiffUtil.ItemCallback areContentsTheSame() 方法始终返回 true。调试代码我发现旧的和新的项目完全相同(旧的状态消失了)。因此,ListAdapter onBindViewHolder() 方法不会被调用来更新列表中的相应行(只有项目的顺序通过漂亮的动画改变)。

在 Stackoverflow 上查看其他问题,看来这是许多开发人员都面临的常见问题:

ListAdapter not updating item in reyclerview

ListAdapter not updating when editing content

DiffUtil.Callback not working as expected

Items in Recyclerview + Listadapter won't redraw on update

ListAdapter with DiffUtil.ItemCallback always considers objects the same

When submitting a new list to RecyclerView ListAdapter the diff check always returns true for areContentsTheSame()

However none of the above answers (if any) have provided a correct solution.

它对我有用的唯一方法是每次观察者发出新结果时在 ListAdapter 上调用 notifyDataSetChanged()

但是,如果通过强制 RecyclerView 重新绘制其内容(它拥有的所有项目)而放弃了您可以获得的所有出色性能,那么使用 ListAdapter 和 SubmitList() 来通知更改的全部意义是什么?到目前为止显示)?

  1. notifyDataSetChanged() :

尽管它有效,但如果您决定首先使用 ListAdapter,那么肯定不是正确的方法。

  • viewModel.getObjects().observe(this, listOfObjects -> listAdapter.submitList(new ArrayList<>(listOfObjects))); :
  • 没用。

    更新列表中的项目后,我希望看到相应行在 UI 上发生的相应更改(不仅仅是排序顺序)。

    最佳答案

    我不知道这是否是针对此特定情况的解决方案,但从描述来看,它听起来与我最近经历过的事情完全一样。

    我第一次使用新的 Room + LiveData + ViewModel + DiffUtils 集成,并且在更新列表后更新 RecyclerView 中的项目时遇到了同样的问题。

    我遇到的问题是由于我对更新列表并允许 DiffUtils 完成其应有的工作的理解。希望以下内容足够清楚:

    我在做什么:

    1. 用户使用对话框更新其项目
    2. RecyclerView 中的列表项已更新为新信息
    3. Room 会触发 LiveData 观察者,因为某些东西可能有改变了
    4. RecyclerView DiffUtils 尝试检查之间的任何差异旧适配器列表和新适配器列表
    5. 未检测到任何新内容
    6. 适配器不会被触发来更新其 UI

    我的错误是认为问题出在.5中,导致我花了半天时间来回调试问题。最终我偶然发现了一个SO问题(目前找不到它),它引导我找到了问题的正确根源。该问题确实位于 .2 - 更新列表中的项目。

    这就是问题所在,因为我们甚至在 DiffUtils 有机会比较新旧列表更改之前就用新更改更新了 CURRENT 适配器列表。这意味着每次 DiffUtils 总是将列表与已包含新列表所做更改的旧列表进行比较。

    解决方案?不要更新列表项,因为它是一个对象,并且列表对象保留相同的引用,从而导致同一实例在使用/引用的任何地方都被更新。相反,克隆项目对象(如在深度克隆中,我知道这可能很烦人),应用用户对该克隆对象所做的更改,然后使用该克隆来更新房间数据库中的项目条目。不要用克隆替换适配器列表项,保留原始列表项,我们只想更新数据库中的信息,而不是列表,因为 DiffUtils 会处理这一点。

    我们在这里实质上做的是为我们的房间数据库创建一个更新有效负载,然后它将触发 LiveData 观察者将旧列表与新列表(包含更新的项目数据)进行比较,从而在两者之间进行预期的更改检测列表。

    <小时/>

    简而言之;

    这样做:

    • 深度克隆适配器列表项
    • 仅使用新信息更新克隆
    • 使用克隆信息更新数据库

    不要这样做:

    • 直接更新适配器列表项
    • 使用列表项信息更新数据库
    <小时/>

    关于android - 更新 ListAdapter 上的项目后,DiffUtil ItemCallback areContentsTheSame() 始终返回 true,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57876118/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com