未调用Android LiveData的Observer(但使用observeForever)

时间:2018-04-23 12:59:10

标签: android realm android-architecture-components android-livedata

我在Fragment上有一个ViewPager,其中显示了一个项目列表。点击一个,会打开一个新的详细信息 - Activity,您可以在其中操作此项(例如更改名称)。当您返回列表时,我希望列表/项目反映更新。

我正在使用RealmLiveData的组合(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()工作,我只能想到一个错误的生命周期,观察者被标记为“已停止”但在回来时没有“恢复”?

编辑1

如上所述,这是将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时,观察者会立即被调用,而我仍处于细节活动状态(因为片段只停止但仍处于活动状态?!)。

1 个答案:

答案 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
        }
    }
}