我现在正在使用最新的Android体系结构组件,尤其是ViewModel和LiveData。
我的情况是SingleLiveEvent建议的here是相关的,即我返回了错误,并且只想显示一次警报。在向Activity传递值之前,我需要将错误映射到该 View 的一个更合适的对象。我为此使用了转换。
所以最后,我有一个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(不是框架的一部分)和Transformations是否不应该一起工作?
最佳答案
我发现这是由于Transformations
使用MediatorLiveData
,它使用SingleLiveEvent
作为引用源。此源用于注册和注销本身作为观察员。
但是,SingleLiveEvent
在注册时引入了中间观察者。 SingleLiveEvent
引用此中间观察者,并且不知道MediatorLiveData
。
在删除时,MediatorLiveData
尝试从SingleLiveEvent
中注销自己作为观察者的身份。由于SingleLiveEvent
不知道,因此保留了中间观察者。
最后,该过程不是对称的,并且随着时间的流逝(随着用户转动电话),SingleLiveEvent
具有越来越多的观察者。
我不知道我是否错过了某件事,或者是否不将MediatorLiveData
与SingleLiveEvent
一起使用,但是我找到了针对自己特定问题的解决方案。
我在SingleLiveEvent
中添加了对中间观察者的引用,并且重写了removeObserver()
方法以除去中间观察者,而不是(仅)MediatorLiveData
。我对这种解决方案不是很自信,因为我不熟悉LiveData
的内部。特别是,仅当SingleLiveEvent
仅与MediatorLiveData
一起用作观察者时(例如,如果Activity观察到SingleLiveEvent
时才如此),并且只有一个观察者时(对于SingleLiveEvent
才有意义),此解决方案才有效。可能还有其他限制。
这是我添加的用于删除正确观察者的代码(singleLiveEventIntermediateObserver
是在Observer
方法中实例化的匿名observe()
):
@Override
public void removeObserver(@NonNull Observer<T> observer) {
super.removeObserver(observer);
if (this.singleLiveEventIntermediateObserver != null) {
super.removeObserver(this.singleLiveEventIntermediateObserver);
}
}