Android架构组件LiveData源码分析

本文主要从源码角度介绍架构组件LiveData的实现原理,默认读者已经熟悉LiveData的基本使用。

观察者模式与发布-订阅模式

之前一直没有特别关注过观察者模式与发布-订阅模式的区别,刚好借此机会去了解了一下。简单来说,两者的核心区别是:

在观察者模式的实现中,观察者(订阅者)是由发布者来维护的,也就是说,发布者是可以感知到观察者的。

但是在发布-订阅模式中,会有一个专门的中介来维护订阅者,发布者与订阅者是无法直接交互的,它们是无法感知另一方的存在的。

具体的细节可以参考这篇文章:观察者模式 vs 发布-订阅模式

功能与使用场景

功能
  • 可以包装数据,使之可被观察,达到响应式的效果。
  • 与页面的生命周期是绑定的,防止内存泄露。
  • 有类似RxJava中运算符的实现,数据处理更灵活。
使用场景

多数情况是搭配ViewModel与Lifecycle组件一起使用,使ViewModel具有响应式的效果。

整体架构图

整体采用了观察者模式,核心的类结构图如下:

image-20181029194637438

简单介绍下其中的关键类:

  • 抽象类LiveData:架构组件的核心类,代表着可被观察的数据本身,是观察者模式中的发布者,负责被观察数据的维护、观察者的维护以及数据变化后的消息分发。
  • Observer接口:代表着观察者,只有一个最简单的 onChanged()方法用于接收变化消息。
  • 抽象类ObserverWrapper:顾名思义,Observer的Wrapper,扩展了Observer的功能,使之不仅仅是接收消息那么简单,例如其具体实现LifecycleBoundObserver就赋予了Observer与Lifecycle组件并用的功能。

源码分析

LiveData的源码不多,具体如下

观察者模式在LiveData中如何实现

观察者模式主要涉及观察者注册、观察者维护、消息发送三个部分。

1、先来看看观察者的注册

以LiveData的observe()/observeForever()方法为入口,这里以observe()为例,两者的区别后面再介绍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
// 如果观察者已经DESTROYED,就不再订阅LiveData
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// 将Observer放入mObservers(观察者map)中
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
// 一个Activity/Fragment等仅能有一个observer
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与ObserverWrapper放入map中维护。

2、如何移除观察者

移除观察者与注册观察者类似,如果Observer是有生命周期的,那就会根据Observer的生命周期变化自动移除,具体实现看LifecycleBoundObserver.onStateChanged()

1
2
3
4
5
6
7
8
9
10
11
12
13
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;

@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
// LiveData的removeObserver()会直接从map中移除Observer
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
}

如果Observer没有生命周期,那么就需要外部调用LiveData的removeObserver()完成移除操作。

3、如何向观察者发送数据变化的通知

数据的变化以LiveData.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
26
27
28
29
30
31
32
33
34
35
36
37
// 被观察的数据,值只能通过setValue改变。
private volatile Object mData = NOT_SET;

@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
// mVersion用于记录当前通知的版本,Observer也会记录最近收到的版本,如果不一致则会调用一次onChange
// 主要用于实现有生命周期的Observer在回复活跃后,再接收一次错过的消息的最后一条
mVersion++;
mData = value;
// 分发消息给观察者
dispatchingValue(null);
}

private void dispatchingValue(@Nullable ObserverWrapper initiator) {
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
}
}

private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// 不会通知非Active的Observer
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
// 最终调用通知方法
observer.mObserver.onChanged((T) mData);
}

前面提到如果Observer在恢复活跃后会收到最近的一次变化,其具体实现在ObserverWrapper的activeStateChanged()中,即恢复活跃后会调用activeStateChanged,然后调用dispatchingValue(),代码比较简单,这里就不再贴出来了。

Transformations如何实现LiveData转换

LiveData还可以做到类似RxJava中运算符的一些功能,具体实现方式如下。

以map为例,实现的关键在于类MediatorLiveData,它本身就是一个LiveData,并且它持有另外一个LiveData,所以它既是一个观察者,又是一个发布者。

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
26
27
28
29
30
31
32
33
34
35
public class MediatorLiveData<T> extends MutableLiveData<T> {
// LiveData<?>是被Source<?>观察的发布者,也是未经过Transformations转换的原始发布者
private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();

@MainThread
public <S> void addSource(@NonNull LiveData<S> source, Observer<S> onChanged) {
Source<S> e = new Source<>(source, onChanged);
Source<?> existing = mSources.putIfAbsent(source, e);
if (hasActiveObservers()) {
// 将observer注册到livedata
e.plug();
}
}

// Source使得MediatorLiveData成为观察者
private static class Source<V> implements Observer<V> {
final LiveData<V> mLiveData;
// 这个mObserver是属于Transformations的,用于通知Transformations数据变化了
final Observer<V> mObserver;
int mVersion = START_VERSION;

Source(LiveData<V> liveData, final Observer<V> observer) {
mLiveData = liveData;
mObserver = observer;
}

@Override
public void onChanged(@Nullable V v) {
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
mObserver.onChanged(v);
}
}
}
}

接着再看Transformations的map的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@MainThread
public static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source,
@NonNull final Function<X, Y> func) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
@Override
public void onChanged(@Nullable X x) {
// 将func作用于MediatorLiveData并通知外部
result.setValue(func.apply(x));
}
});
// 外部实际拿到的是MediatorLiveData
return result;
}

总结上面的代码就是,MediatorLiveData中的Observer监听原始LiveData的变化,当其变化后MediatorLiveData中的Observer就将Transformations提供的func作用于变化后的数据,然后再将这个数据通过MediatorLiveData中的LiveData通知到外部。

参考资料

LiveData Overview

观察者模式 vs 发布-订阅模式