我一直在使用Paging Library实施新的RecyclerView,并在Architecture Components之上构建应用。
填充列表的数据来自Room数据库。实际上,它是从网络中获取的,存储在本地数据库中并提供给列表。
为了提供构建列表所需的数据,我实现了自己的自定义PageKeyedDataSource。一切都按预期工作,除了一个小细节。显示列表后,如果列表的行元素的数据发生任何更改,则不会自动更新。因此,如果我的列表显示的是具有字段 name 的项目列表,并且突然,此字段在本地Room数据库中针对某个行项目进行更新,则该列表不会更新自动排UI。
仅当使用自定义DataSource时才会发生此行为,这与通过DAO自动获取DataSource的方式不同,直接返回DataSource Factory。但是,我需要实现自定义DataSource。
我知道可以通过调用DataSource上的 invalidate()方法来重新更新列表。但是,如果应用程序一次显示2个列表(例如每个半屏),并且此项目出现在两个列表中,则需要分别为两个列表调用 invalidate()。 / p>
我想过一个解决方案,其中不是使用项目类的实例来填充每个ViewHolder,而是使用LiveData包装的版本来制作每个LifeCycleOwner行观察其自身项目的更改,并在必要时更新该行UI。尽管如此,我认为这种方法存在一些缺点:
我完全不知道,即使考虑到这些缺点,它看起来似乎是一种体面的方法,或者,如果你们中的任何人知道任何其他更清洁,更好的方法来管理它。
提前谢谢。
答案 0 :(得分:0)
自从上次检查该问题以来已经有一段时间了,但是对于任何感兴趣的人,这都是我的问题的原因+我为了使library从LiveData到{{3}避免使用问题中说明的解决方法。
我的特定问题是由于Kotlin的ViewHolder使用不当所致。使用它们时,请务必注意(如文档中所述), 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
}
这在实现Data Classes的 DiffCallback 时特别重要,就像我们处于示例的 MyClass2 这样的场景中一样,无论我们执行多少次更新我们PagedListAdapter数据库中的 name 字段,因为 DiffCallback 的 areContentsTheSame()方法可能总是会返回< em> true ,使列表从不更新该更改。
如果上述原因不是问题的原因,或者您只是想能够从 ViewHolder 正确观察 LiveData 实例,我开发了一个该库可为任何 ViewHolder 提供 Lifecycle ,从而使其能够以正确的方式观察 LiveData 实例(而不必使用本教程中介绍的解决方法问题)。