3

我现在正在使用最新的 Android 架构组件,尤其是 ViewModel 和 LiveData。

我的情况是此处建议的SingleLiveEvent是相关的,即我返回一个错误并且我只想显示一次警报。在向 Activity 发出值之前,我需要将我的错误映射到更适合视图的对象。我为此使用了转换。

所以最后,我有一个看起来像这样的 ViewModel:

public LiveData<ViewState> getStateForView() {
    final LiveData<NetworkState> liveState = myRepository.getState();
    return Transformations.map(liveState, myMapper::map);
}

在我的存储库中,我在哪里使用 SingleLiveEvent:

public LiveData<NetworkState> getState() {
    myNetworkState = new SingleLiveEvent<>();
    return myNetworkState;
}

这工作得很好,但我注意到当方向多次更改时,我的事件并没有一直传播。在调试时,我注意到观察者注册和移除之间没有对称性:

  • 在注册时,我的 SingleLiveEvent 的观察者是我 SingleLiveEvent 中的匿名观察者类

注册调试

  • 在删除时,要从我的 SingleLiveEvent 中删除的观察者是 MediatorLiveData(实际上是在观察我的 SingleLiveEvent 中的早期匿名类)

删除调试

发生的情况是,我的初始观察者永远不会从 SingleLiveEvent 的观察者中移除(因此,如果方向更改多次,我的 SingleLiveEvent 有多个观察者)。

我无法弄清楚为什么在移除时这不是同一个观察者。在没有转换步骤的情况下复制它时,不存在这样的问题。

有没有人暗示过这种行为?SingleLiveEvent(不是框架的一部分)和转换不应该一起工作吗?

4

1 回答 1

3

我发现这是因为Transformations使用 a MediatorLiveData,它使用 theSingleLiveEvent作为引用源。此源用于注册和删除自己作为观察者。

但是,SingleLiveEvent在注册时引入了一个中间观察者。引用此中间SingleLiveEvent观察者并且不知道MediatorLiveData.

在删除时,MediatorLiveData尝试将自己从SingleLiveEvent. 由于SingleLiveEvent不知道它,它保持中间观察者。

最后,这个过程是不对称的,随着时间的推移(用户转动手机),SingleLiveEvent观察者越来越多。

我不知道我是否遗漏了某些东西,或者是否MediatorLiveData不能与 一起使用SingleLiveEvent,但我找到了针对我的具体问题的解决方案。

我在 中添加了对中间观察者的引用,SingleLiveEvent并且我重写了它的removeObserver()方法来删除中间观察者,而不是(仅)删除MediatorLiveData. 我对这个解决方案不太有信心,因为我不熟悉LiveData. 特别是,该解决方案仅在SingleLiveEvent仅与MediatorLiveData作为观察者一起使用时才有效(即,如果 Activity 观察到 则无效SingleLiveEvent),并且仅当存在单个观察者时(这在 a 的情况下才有意义SingleLiveEvent)。可能还有其他限制。

这是我为删除正确的观察者而添加的代码(是方法中实例化singleLiveEventIntermediateObserver的匿名):Observerobserve()

@Override
public void removeObserver(@NonNull Observer<T> observer) {
    super.removeObserver(observer);
    if (this.singleLiveEventIntermediateObserver != null) {
        super.removeObserver(this.singleLiveEventIntermediateObserver);
    }
}
于 2017-11-27T16:42:52.983 回答