LiveData
LiveData组件是Jetpack新推出基于观察者的消息订阅/分发组件,具有宿主(Activity/Fragment)生命周期感知能力,这种感知能力可确保LiveData仅分发消息给处于活跃状态的观察者,即只有处于活跃状态的观察者才能收到消息。
出现的问题
业务场景 A页面有一个持续性的业务任务,并同时播放BGM,任务的成功失败依赖后端下发的IM消息控制,在业务层则通过LiveData去分发结果
问题: A页面跳转到另一个页面B之后,任务仍然执行,BGM任然播放,但停留在页面B的时候,失败或者成功的结果回调没有执行,只有返回页面A才执行回调,出现BUG.
原因分析: LiveData的结果没有分发出去,LiveData是一个LifecycleOwner,他可以直接感知activity或fragment的生命周期,LiveData了解UI界面的状态,如果activity不在屏幕上显示,livedata不会触发没必要的界面更新,如果activity已经被销毁,会自动清空与observer的连接,意外的调用就不会发生。
对于不活跃的页面则不会下发结果,活跃状态:通常情况下等于Observer所在宿主处于started、resumed状态,如果使用observeForever注册的,则一直处于活跃状态。
所以改个方法注册就OK了。
源码:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
通过observer注册的观察者会被包装成LifecycleBoundObserver,它能监听宿主被销毁的事件,从而主动的把自己反注册,避免内存泄漏,此时观察者是否处于活跃状态就等于宿主是否可见
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
onStateChanged 宿主的状态回调,shouldBeActive这个方法会判断是否处于活跃状态,
再看下LifecycleRegistry这个类:
static State getStateAfter(Event event) {
switch (event) {
case ON_CREATE:
case ON_STOP:
return CREATED;
case ON_START:
case ON_PAUSE:
return STARTED;
case ON_RESUME:
return RESUMED;
case ON_DESTROY:
return DESTROYED;
case ON_ANY:
break;
}
throw new IllegalArgumentException("Unexpected event value " + event);
}
生命周期的对应,判断是否处于活动状态。
很简单的一个BUG,过了一遍Livedata的源码备忘。
|