Android-Jetpack笔记-LiveData

LiveData即有生命的数据,通过观察者模式实现,当数据发生变化时可以收到回调。同时还具备感知宿主生命周期的能力。

Jetpack笔记代码

本文源码基于SDK 29

使用

引入依赖:

1
2
3
def lifecycle_version = "2.2.0"
//extensions包含Lifecycles、LiveData、ViewModel
implementation "android.arch.lifecycle:extensions:$lifecycle_version"

在act中使用,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//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才会收到回调,这是因为,

1
2
3
4
5
6
7
8
9
10
//LiveData.java
private void considerNotify(ObserverWrapper observer) {
if (!observer.shouldBeActive()) {
//判断是否活跃
observer.activeStateChanged(false);
return;
}
//从包装类中取出观察者,回调
observer.mObserver.onChanged((T) mData);
}

shouldBeActive有两个实现,我们先看这个,

1
2
3
4
5
6
//LiveData.LifecycleBoundObserver
@Override
boolean shouldBeActive() {
//只有getLifecycle().getCurrentState()大于等于STARTED,才通知
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

看下日志,可见只有onStart、onResume、onPause时,getLifecycle().getCurrentState()大于等于STARTED,

再看下另一个实现,

1
2
3
4
5
6
//LiveData.AlwaysActiveObserver
@Override
boolean shouldBeActive() {
//直接返回true
return true;
}

当调用observeForever时,创建的包装类就是AlwaysActiveObserver,所以,这时可以在所有生命周期都收到通知,

当然,调用observeForever的话,由于他的包装类没有进行removeObserver,需要在业务层手动移除,否则可能会造成内存泄漏,

  • observe:包装类是LifecycleBoundObserver(有活跃边界),内部会调removeObserver
  • observeForever:包装类是AlwaysActiveObserver (总是活跃),需要手动调removeObserver

优缺点

  • 优点:
    • 使用简单,可以避免内存泄漏,RxJava则需结合RxLifecycle
    • 能感知生命周期,在页面活跃状态才进行通知,可以避免页面不可见时还在占资源

参考文章