具有自定义数据源的分页库不会在房间更新时更新行

Paging Library with custom DataSource not updating row on Room update

我一直在实施新的 Paging Library with a RecyclerView with an app built on top of the Architecture Components

填写列表的数据是从Room数据库中获取的。其实就是从网络上抓取,存储到本地数据库,提供给列表。

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

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

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

我想到了一个解决方案,而不是使用项目 class 的实例来填充它的每个 ViewHolder, it uses a LiveData 包装版本,让每一行自己观察变化项并在必要时更新该行 UI。尽管如此,我还是看到了这种方法的一些缺点:

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

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

提前致谢。

自从上次检查这个问题以来已经有一段时间了,但是对于任何感兴趣的人,这是我的问题的原因 + library I made to observe LiveData properly from a ViewHolder(以避免必须使用问题中解释的解决方法)。

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

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
}

这在实现 PagedListAdapter's DiffCallback, as if we are in a example's MyClass2 like scenario, no matter how many times we update the name field in our Room 数据库时特别重要,因为 DiffCallbackareContentsTheSame() 方法可能是总是 return true,使列表永远不会更新该更改。


如果上面解释的原因不是您问题的原因,或者您只是想能够从 ViewHolder[= 中正确观察 LiveData 实例38=],我开发了一个小型库,它为任何 ViewHolder 提供 Lifecycle,使其能够观察 LiveData 实例以正确的方式(而不是必须使用问题中解释的解决方法)。

https://github.com/Sarquella/LifecycleCells