我在Fragment
上有一个ViewPager
,其中显示了一个项目列表。点击一个,会打开一个新的详细信息 - Activity
,您可以在其中操作此项(例如更改名称)。当您返回列表时,我希望列表/项目反映更新。
我正在使用Realm
和LiveData
的组合(RealmChangeListener
已添加并更新实际value
的{{1}})。
另外,我正在使用https://medium.com/@BladeCoder/architecture-components-pitfalls-part-1-9300dd969808中的“reobserve”方法(#3),当重新添加ViewPager的片段时,该方法正常工作。
当改变列表片段本身上的列表项时,会调用观察者并且一切都很好。但是当从不同的活动(细节)进行更改时,不会调用LiveData-observer。
但是,当使用LiveData
代替observeForever()
时,即使从其他活动(这是我想要的)进行更改,观察者也会被称为。
片段仅已停止(当您从详细信息返回列表时恢复)。它没有分离,没有被破坏,它的视图仍然存在等等所以observeForever-observer可以很好地更新UI(即使不可见)。
但是我想使用“添加并忘记” - 正常observe(LifecycleOwner)
的方法,我不需要移除观察者。
有没有人知道为什么没有调用观察者?如上所述,片段只是停止并且视图仍然存在(并且当更改发生在同一个活动但不是另一个活动时调用它。)
由于observe()
工作,我只能想到一个错误的生命周期,观察者被标记为“已停止”但在回来时没有“恢复”?
如上所述,这是将observeForever()
作为RealmResult
(来自blog post at realm)的代码:
LiveData
这很好用。我Realm.getDefaultInstance()
.where<Model>()
.findAllAsync()
.asLiveData()
fun <T : RealmModel> RealmResults<T>.asLiveData() = RealmResultsRealmData(this)
class RealmResultsRealmData<T : RealmModel>(private val results: RealmResults<T>) : LiveData<RealmResults<T>>() {
private val listener = RealmChangeListener<RealmResults<T>> { realmResults ->
value = if (realmResults.isValid) realmResults else null
}
// region LiveData
override fun onActive() {
results.addChangeListener(listener)
}
override fun onInactive() {
results.removeChangeListener(listener)
}
// endregion
}
中的ViewModel
来电realm.close()
,所以这也应该没问题。
如上所述,我不认为问题出在领域,因为它在使用onCleared()
时有效,但在observeForever()
上使用普通observe()
时无效。 Realm只填充LiveData
并且已经过验证(使用LiveData
)。
我最好的猜测仍然是使用observeForever()
时观察者的生命周期。但我不明白为什么在片段“恢复”时不会调用它。 The docs说“观察员在从非活动状态变为活动状态时也会收到更新”。
没有定义什么是“活跃”状态,但我想这至少是“开始”,当我从细节活动回来时,我的片段进入这种状态。那么应该使用observe()
的最新值来调用观察者?相反,当使用LiveData
时,观察者会立即被调用,而我仍处于细节活动状态(因为片段只停止但仍处于活动状态?!)。
答案 0 :(得分:2)
似乎addChangeListener()
不使用当前值调用监听器。
realm-examples中的LiveRealmResults类在构造函数中手动完成此操作(当结果已加载时,因此仅用于同步查询)。
if (results.isLoaded) {
// we should not notify observers when results aren't ready yet (async query).
// however, synchronous query should be set explicitly.
value = results
}
对于 async -one,仅在查询返回时才调用侦听器(因此,大多数情况下此方法有效,因为LiveData
已处于 active (已从系统调用onActive()
,并添加了侦听器。)
在我的情况下(在LiveData
为无效 的情况下更改模型的情况下),当它会再次变为活动状态(如上所述,addChangeListener()
不会使用当前值调用侦听器)。
因此,我的用户界面(观察LiveData
)未收到通知,但仍显示旧数据。
解决方法
我也通过将来自示例构造函数的相同行添加到onActive()
(从示例复制)中来解决此问题。这样,当LiveData
处于活动状态时,将使用当前值调用监听器 (但在未加载结果时不会在初始调用上,因此不会进行两次调用)。
override fun onActive() {
super.onActive()
if (results.isValid) { // invalidated results can no longer be observed.
results.addChangeListener(listener)
if (results.isLoaded) {
value = results
}
}
}