【问题标题】:Paging Library with custom DataSource not updating row on Room update带有自定义数据源的分页库在房间更新时不更新行
【发布时间】:2023-03-21 17:18:02
【问题描述】:

我一直在用RecyclerView 实现新的Paging Library,并在Architecture Components 之上构建了一个应用程序。

填充列表的数据来自Room 数据库。其实就是从网络上抓取,存入本地数据库,提供给列表。

为了提供构建列表所需的数据,我实现了自己的自定义PageKeyedDataSource。除了一个小细节外,一切都按预期工作。列表显示后,如果列表行元素的数据发生任何变化,则不会自动更新。因此,例如,如果我的列表显示具有字段 name 的项目列表,并且突然,该字段在本地 Room 数据库中针对某个行项目进行了更新,则该列表不会更新自动行 UI。

此行为仅在使用自定义数据源时发生,这与从DAO 自动获取数据源时不同,通过直接返回DataSource Factory。但是,我需要实现一个自定义数据源。

我知道它可以通过调用 DataSource 上的 invalidate() 方法来重建更新的列表。但是,如果应用程序一次显示 2 个列表(例如每个半屏),并且该项目出现在两个列表中,则需要分别为两个列表调用 invalidate()

我想到了一个解决方案,它不是使用项目类的实例来填充每个 ViewHolder,而是使用它的 LiveData 包装版本,以使每一行观察其自身项目的变化并在必要时更新该行 UI。不过,我认为这种方法有一些缺点:

  1. 必须将LifeCycleOwner(例如包含 RecyclerView 的 Fragment)传递给 PagedListAdapter,然后将其转发给 ViewHolder,以便观察 LiveData 包装的项目。
  2. 将为每个列表的新行注册一个新的观察者,所以我根本不知道它是否有过多的计算和内存成本,考虑到应用程序中的每个列表都会这样做,它有很多列表在里面。
  3. 例如,由于 LifeCycleOwner 观察 LiveData 包装的项目将是包含 RecyclerView 的 Fragment,而不是 ViewHolder 本身,因此每次该项目发生更改时都会通知观察者,即使包含该项目的行在那一刻甚至不可见,因为列表已被滚动,在我看来,这似乎是一种资源浪费,可能会不必要地增加计算成本。

我完全不知道,即使考虑到这些缺点,这是否是一种不错的方法,或者,也许你们中的任何人都知道任何其他更清洁、更好的管理方法。

提前谢谢你。

【问题讨论】:

  • 您找到解决问题的方法了吗?

标签: android list android-livedata android-architecture-components android-paging


【解决方案1】:

自上次检查此问题以来已经有一段时间了,但对于任何感兴趣的人,这是我的问题的原因 + library 我从 ViewHolder 正确观察 LiveData (以避免不得不使用解决方法问题中解释)。

我的具体问题是由于对 Kotlin 的 Data Classes 使用不当造成的。使用它们时,请务必注意(如文档中所述),toString()equals()hashCode()copy() 将只考虑在类的构造函数中声明的所有属性,而忽略在类的主体中声明的那些属性。一个简单的例子:

data class MyClass1(val prop: Int, val name: String) {}

data class MyClass2(val prop: Int) {
    var name: String = ""
}

fun main() {   
    val a = MyClass1(1, "a")
    val b = MyClass1(1, "b")

    println(a == b) //False :) -> a.name != b.name

    val c = MyClass2(2)
    c.name = "c"
    val d = MyClass2(2)
    d.name = "d"

    println(c == d) //True!! :O -> But c.name != d.name
}

这在实现PagedListAdapterDiffCallback时特别重要,就像我们在一个示例的MyClass2一样的场景中,无论我们更新多少次Room 数据库中的 name 字段,因为 DiffCallbackareContentsTheSame() 方法可能总是会返回 true,使列表永远不会更新该更改。


如果上面解释的原因不是您的问题的原因,或者您只是希望能够从 ViewHolder 正确观察 LiveData 实例,我开发了一个小为任何 ViewHolder 提供 Lifecycle 的库,使其能够以正确的方式观察 LiveData 实例(而不必使用在问题)。

https://github.com/Sarquella/LifecycleCells

【讨论】:

    猜你喜欢
    • 2019-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2011-12-21
    • 1970-01-01
    • 2022-11-09
    • 1970-01-01
    相关资源
    最近更新 更多