我现在正在使用最新的Android架构组件,尤其是ViewModel和LiveData。
我遇到SingleLiveEvent建议here相关的情况,即我返回错误,我只想显示一次警报。在向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(不是框架的一部分)和转换不应该一起工作吗?
答案 0 :(得分:2)
我发现这是因为Transformations
使用MediatorLiveData
,SingleLiveEvent
使用SingleLiveEvent
作为参考来源。该来源用于作为观察者注册和删除自己。
但是,SingleLiveEvent
在注册时引入了一名中间观察员。 MediatorLiveData
引用此中间观察者,但不知道MediatorLiveData
。
在删除时,SingleLiveEvent
尝试从SingleLiveEvent
注销自己作为观察者。由于SingleLiveEvent
不知道它,它保留了中间观察者。
最后,这个过程并不是对称的,随着时间的推移(当用户转动手机时),MediatorLiveData
有越来越多的观察者。
我不知道我是否遗漏了某些内容,或SingleLiveEvent
是否与SingleLiveEvent
不一致,但我找到了针对我的具体问题的解决方案。
我在removeObserver()
中添加了对中间观察者的引用,并且我已经覆盖了它的MediatorLiveData
方法以删除中间观察者而不是(仅)LiveData
。我对这个解决方案不太自信,因为我不熟悉SingleLiveEvent
的内部。特别是,此解决方案仅在MediatorLiveData
仅与SingleLiveEvent
作为观察者使用时才有效(即,如果活动观察SingleLiveEvent
),并且仅当有一个观察者时(这在singleLiveEventIntermediateObserver
)的情况下是有意义的。可能还有其他限制。
以下是为删除正确的观察者而添加的代码(Observer
是observe()
方法中实例化的匿名@Override
public void removeObserver(@NonNull Observer<T> observer) {
super.removeObserver(observer);
if (this.singleLiveEventIntermediateObserver != null) {
super.removeObserver(this.singleLiveEventIntermediateObserver);
}
}
:
domain1.com