前言
https://developer.android.com/reference/android/arch/lifecycle/LiveData?hl=zh-cn
https://developer.android.com/topic/libraries/architecture/livedata?hl=zh-cn
LiveData在整个架构体系中起到了桥梁作用,此外LiveData还持有了数据,并做相应的分发。
LiveData与外界也是个被观察者与观察者的关系。
在观察者模式的基础上,还为其加上了LifecycleObserver
,让其感知生命周期变化可以自己解注册观察者,不可感知与可感知分别对应了observerForever()
和observer()
两个方法。
和LiveData
相关的类不多,但是各个很有趣。
LiveData
上文说过,LiveData
中有两种不同的注册观察者的方式,一种是带有生命周期感知的注册方式,另一种是直接注册(需要手动解注册)。
这其中分别对应了LiveData
的中的内部类AlwaysActiveObserver
与LifecycleBoundObserver
,这两个为直接继承自ObserverWrapper
。
ObserverWrapper
内部也很简单,对LiveData
是否处于激活状态做了处理与封装,当观察者数量mActiveCount
首次大于0时且LiveData
处于激活状态时,调用onActive()
;当观察者数量mActiveCount
等于0且LiveData
不处于激活状态时,调用onInactive()
。
LifecycleBoundObserver
中集成了LifecycleObserver
的子类GenericLifecycleObserver
,用来对生命周期做出改变,shouldBeActive()
方法则判断了当前LifecycleOwner
的当前状态至少为STARTED
才能变为激活态。
AlwaysActiveObserver
则很简单,shouldBeActive()
始终返回true
。
下面分别让看一下带有生命周期与不带有生命周期的使用LiveData
的时序图:
observer(owner, observer)
:
observerForever(observer)
:
这两个路线的逻辑都很简单,这里就不赘述了,最后都在considerNotify()
完成了任务分发:
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
...
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
...
observer.mObserver.onChanged((T) mData);
}
MediatorData
该类直接继承自LiveData
,除了可以使用LiveData
的基础能力外,还具有将多个LiveData
组合在一起的能力。任意一个被组合的LiveData
发生变化时,MediatorData
的观察者都可以收到改变通知。
其中的关键在于Source
这个类,它不仅组合持有LiveData
与Observer
,同时还继承自Observer
,这就代表它具有在LiveData
数据发生变化时,将通知再次分发的能力。
Transformations
与上面不同的是,LiveData
提供了持有数据和分发的能力,MediatorLiveData
则提供了将多个LiveData
组合在一起的能力,Transformations
虽然是个工具类,但是却提供了转换LiveData
的能力。
LiveData类的转换工具类
可以使用工具类在观察者的生命周期中传递信息。除非观察者正在观察返回的LiveData对象,否则不会计算转换。
因为转换是懒惰地计算的,所以与生命周期相关的行为被隐式传递下去,而不需要额外的显式调用或依赖。
这种能力分为两种:
- 对LiveData传递的数据进行处理转换的能力。例如:本来传递的是 “test”,经过转换可以将其加工成"test+test"。
- 对LiveData传递的数据进行二次包装让其成为LiveData的能力。 例如:第一个LiveData的传递数据结果为用户名,但是实际上还想根据这个用户名查询用户的详细信息,就可以根据这个LiveData的结果再包装成第二个可以查询详细信息的LiveData。
首先看下其第一个能力:map
- 映射
由于MediatorLiveData
可以将多个LiveData
进行组合,并观察其LiveData
的数据变化,这就可以利用其Observer.onChanged()
这个抓手,将结果结果数据进行一次处理,再将其分发给result
。
public static <X, Y> LiveData<Y> map(LiveData<X> source, final Function<X, Y> func) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
public void onChanged(@Nullable X x) {
// 对x数据进行处理(apply) 并对结果进行分发
result.setValue(func.apply(x));
}
});
return result;
}
再看下第二个能力:switchMap
- 转换映射
虽然switchMap
内部嵌套了多次,但是可以将其分离为两层:
- 第一层
result.addSource(trigger, ...
,该操作理解为是为了获得懒计算的能力,由于LiveData
特性决定,只有观察者注册时onChanged
才会被调用,那么位于其中func.apply()
才会执行计算。 - 第二层
result.addSource(mSource,...
,该操作是为了获取经过func.apply
得到的LiveData
的计算结果,只有得到新的结果,才能再借助result
的能力将其分发给观察者。
public static <X, Y> LiveData<Y> switchMap( LiveData<X> trigger, Function<X, LiveData<Y>> func) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
// 为func提供懒惰计算的能力
result.addSource(trigger, new Observer<X>() {
LiveData<Y> mSource;
public void onChanged(@Nullable X x) {
// 对x结果进行映射转换,得到一个新的LiveData
LiveData<Y> newLiveData = func.apply(x);
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
result.removeSource(mSource);
}
mSource = newLiveData;
if (mSource != null) {
// 将新的LiveData注册到result中
result.addSource(mSource, new Observer<Y>() {
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}