当前位置: 首页 > 知识库问答 >
问题:

DiffUtil ItemCallback AreContentsSame()在更新ListAdapter上的项后始终返回true

端木皓君
2023-03-14

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

ListAdapter未更新ReyclView中的项

编辑内容时ListAdapter未更新

DiffUtil。回调未按预期工作

Recyclerview Listadapter中的项在更新时不会重新绘制

带有DiffUtil的ListAdapter。ItemCallback始终认为对象是相同的

当向RecyclerView ListAdapter提交新列表时,对于areContentsTheSame()而言,差异检查始终返回true

然而,上述答案(如果有的话)都没有提供正确的解决方案。

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

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

  1. 通知DataSetChanged()

即使它可以工作,但如果您决定首先使用ListAdapter,它肯定不是合适的方法。

没用。

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

共有3个答案

匡祖鹤
2023-03-14

我花了很多时间,直到我发现我的问题和这篇文章描述的一样。我尝试了很多解决方案,但最终我意识到自己在不知不觉中把事情搞砸了。如果您遇到同样的问题,请检查您是否没有首先更新UI,并调用write命令来更新存储库中的值。在我的例子中,我正在更新LiveData对象,然后在Firebase数据库上更新该值。这个问题是因为我的UI正在监听LiveData对象上的更改,所以我的Firebase数据库观察器检测到了更改,调用了ListAdapter,看起来什么都没有更改。

为了解决这个问题,我删除了更新LiveData对象的行,只调用Firebase数据库发送更改。

孙阳旭
2023-03-14

几天前,我遇到了同样的问题。我试图更新适配器中的对象,如下所示:

binding.accept.setOnClickListener {
            existingEntity.taskStatus = "accept"
            listener.onItemClick(existingEntity)
        }

上面的代码正在更新数据库对象,但没有反映在我的回收器视图中。这是因为对对象的引用相同。所以当我更新适配器中的对象时,它会自动更新我列表中的对象。所以我像下面一样修改了我的代码:

binding.accept.setOnClickListener {
            val newEntity = existingEntity.copy()
            newEntity.taskStatus = "accept"
            listener.onItemClick(newEntity)
        }

所以我使用静态编程语言数据类复制()方法创建了一个复制对象,它为我工作。

宇文鸿畴
2023-03-14

我不知道这是否是这个具体案例的解决方案,但从描述来看,这听起来和我最近经历的事情一模一样。

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

我遇到的问题是因为我了解如何更新列表,并允许DiffUtils按其应做的工作。希望以下内容足够清楚:

我在做什么:

  1. 用户使用对话框更新其项目
  2. RecyclerView中的列表项将用新信息更新
  3. Room会触发LiveData observer,因为可能发生了变化
  4. RecyclerView DiffUtils尝试检查旧适配器列表和新适配器列表之间的任何差异
  5. 未检测到任何新内容
  6. 适配器不会被触发以更新其UI

我的错误是认为问题在.5中,这导致我花了半天时间来回调试问题。最后,我偶然发现了一个问题(目前找不到),这让我找到了问题的正确来源。这个问题实际上存在于.2-更新列表中的项目。

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

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

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

这样做:

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

不要这样做:

  • 直接更新适配器列表项
  • 使用列表项信息更新数据库
 类似资料:
  • 编辑的 Laravel版本:5.2.45 PHP版本:5.6 数据库驱动程序 你好 我完成了从laravel 5.1到5.2的更新,并解决了一些问题... 现在我尝试登录,但认证验证密码字段的密码,但在我的数据库密码有另一个名称是senha。 照亮/Auth/EloquentUserProvider.php 您可以看到,函数试图在凭据中找到字符串密码,而它应该是senha 同样的问题与valida

  • 问题内容: 我在这里看到了几个与sqlite更新有关的问题,但无法解决此问题。我无法更新表,它始终为0; 我可以插入和获取数据,但是更新时只有问题。 PS我也试过execSql() 问题答案: 听起来好像没有什么符合您的标准。也许作为测试,您应该通过null作为where条件(这表示更新所有行),并查看是否仍返回0。 如果此后仍返回0,我将确保您实际上已将数据保存在数据库表中。

  • 我正在使用maven eclipse插件来管理我的web应用程序项目的dependecies(eclipse WTP)。在更改依赖项时,我通常执行maven的copy-dependencies目标,将项目JAR复制到WebContent/WEB-INF/lib文件夹。当我更改pom文件中的依赖项时,是否有一种方法可以自动完成此操作?

  • 问题内容: 我以前使用过媒体播放器,但从未遇到过此问题。每当我尝试使用MediaPlayer.create()时,该方法都会使我为null,并且无法播放声音。有什么我想念的吗? 我的sound.mp3在我的原始文件夹中,通过将声音拖到eclipse中的文件夹中,我将其放置在其中。请帮忙,因为我以前玩过声音,所以这真的困扰我:( 问题答案: 如果create() API由于某种原因失败,则返回nul

  • 问题内容: 尽管是有效的类,但以下代码会打印。 文档说方法返回 由 aClassName 命名的类对象,或者如果当前没有加载该名称的类。如果 aClassName 为,则返回。 我也试图获得当前的viewcontroller已加载但仍然得到 可能是什么问题? 更新: 即使尝试这样做,我仍然可以 问题答案: 该函数 确实 适用于(纯和Objective-C派生的)swift类,但是仅当您使用全限定名

  • 问题内容: 我觉得有点愚蠢,但它不起作用: 我有如果给定的用户是unicode。如果字符串中包含或,我想打印成功,但是我总是得到的结果。 问题答案: 隐式锚定到字符串的开头。如果要在字符串中搜索可以在字符串中任何位置的子字符串,则需要使用: 输出: 另外,Python Regexes不需要在开头和结尾都有一个。 最后,我添加到该行的末尾,因为我认为这就是您想要的。否则,您会得到类似的信息,但并不太