LiveData
即有生命的数据,通过观察者模式实现,当数据发生变化时可以收到回调。同时还具备感知宿主生命周期的能力。
本文源码基于SDK 29
使用
引入依赖:
def lifecycle_version = "2.2.0"
//extensions包含Lifecycles、LiveData、ViewModel
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
在act中使用,
class ViewModelActivity extends BaseActivity {
MutableLiveData<String> mLiveData = new MutableLiveData<>();
void onCreate(Bundle savedInstanceState) {
//观察数据变化
mLiveData.observe(this, s -> {
QrLog.e("observe = " + s + "," + getLifecycle().getCurrentState());
});
//设置数据
mLiveData.setValue("onCreate");
}
void onResume() {
//设置数据
mLiveData.setValue("onResume");
}
}
使用起来很简单,下面来看看是怎么实现的。
原理
首先看mLiveData.observe
,
//LiveData.java
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//owner是act对象,在Lifecycles中提到过,他可以作为一个被观察者
//observer是观察者
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
//包装被观察者和观察者
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//存储起来,<观察者,包装类>
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//包装类成为act的观察者,能感知act生命周期
owner.getLifecycle().addObserver(wrapper);
}
来到setValue
,
//LiveData.java
protected void setValue(T value) {
//把值记录起来
mData = value;
//开始分发
dispatchingValue(null);
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
do {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
//遍历包装类
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
} while (mDispatchInvalidated);
}
private void considerNotify(ObserverWrapper observer) {
//从包装类中取出观察者,回调
observer.mObserver.onChanged((T) mData);
}
到这里,流程就已经走完了,值得注意的是,并不是所有生命周期都能观察到值的变化,试着在每个生命周期都setValue一下,会发现只有onStart、onResume、onPause才会收到回调,这是因为,
//LiveData.java
private void considerNotify(ObserverWrapper observer) {
if (!observer.shouldBeActive()) {
//判断是否活跃
observer.activeStateChanged(false);
return;
}
//从包装类中取出观察者,回调
observer.mObserver.onChanged((T) mData);
}
shouldBeActive有两个实现,我们先看这个,
//LiveData.LifecycleBoundObserver
@Override
boolean shouldBeActive() {
//只有getLifecycle().getCurrentState()大于等于STARTED,才通知
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
看下日志,可见只有onStart、onResume、onPause时,getLifecycle().getCurrentState()大于等于STARTED,
再看下另一个实现,
//LiveData.AlwaysActiveObserver
@Override
boolean shouldBeActive() {
//直接返回true
return true;
}
当调用observeForever
时,创建的包装类就是AlwaysActiveObserver
,所以,这时可以在所有生命周期都收到通知,
当然,调用observeForever
的话,由于他的包装类没有进行removeObserver
,需要在业务层手动移除,否则可能会造成内存泄漏,
- observe:包装类是LifecycleBoundObserver(有活跃边界),内部会调removeObserver
- observeForever:包装类是AlwaysActiveObserver (总是活跃),需要手动调removeObserver
优缺点
- 优点:
- 使用简单,可以避免内存泄漏,RxJava则需结合RxLifecycle
- 能感知生命周期,在页面活跃状态才进行通知,可以避免页面不可见时还在占资源
参考文章
本文使用 mdnice 排版