作者:叶志陈
前言
LiveData是Jetpack的基础组件之一,在很多模块中都可以看到其身影。LiveData可以和生命周期绑定,当Lifecycle(例如Activity、Fragment等)处于活跃状态时才进行数据回调,并在Lifecycle处于无效状态(DESTROYED)时自动移除数据监听行为,从而避免常见的内存泄露和NPE问题。
本文就来介绍下LiveData的内部实现逻辑,从而让读者在知道其使用方法之外,还可以了解到其实现原理以及以下几点比较容易忽略的重要特性:
- 一个Observer对象只能和一个Lifecycle对象绑定,否则将抛出异常
- 同个Observer对象不能同时使用observe()和observeForever()函数,否则将抛出异常
- LiveData存在丢值的可能性。当单线程连续传值或者多线程同时postValue时,最终可能只有最后一个值能够被保留并回调
- LiveData 存在仅有部分 Observer 有收到值回调的可能性。当单线程连续传值或者多线程同时传值时,假设是先后传valueA和valueB,可能只有部分Observer可以接收到valueA,然后所有Observer都接收到了valueB
本文所讲的的源代码基于以下依赖库当前最新的release版本:
compileSdkVersion 29
implementation "androidx.lifecycle:lifecycle-livedata:2.2.0"
Observer
LiveData包含两个用于添加数据观察者(Observer)的方法,分别是
- observe(LifecycleOwner , Observer)
- observeForever(Observer)
两个方法的区别对于外部来说只在于是否提供了生命周期安全的保障。
生命周期安全的observe
observe(LifecycleOwner , Observer)方法的函数签名如下所示。传入的LifecycleOwner参数意味着携带了Lifecycle对象,LiveData内部就根据 Lifecycle的生命周期事件的回调变化在合适的时机进行数据通知,并在 Lifecycle对象处于DESTROYED状态时自动移除Observer,这也是LiveData避免内存泄漏的最重要的一个点。
observe(LifecycleOwner , Observer)方法内部首先对observer进行了去重校验,如果之前已经用同个observer对象调用了observe(LifecycleOwner,Observer)方法,而LifecycleOwner不是同一个对象,则直接抛出异常。即一个Observer只允许和单个LifecycleOwner进行绑定。因为如果允许一个Observer同时和多个不同的LifecycleOwner进行绑定的话,这可能会导致当LiveData 数据发生变化时,处于RESUMED状态的LifecycleOwner和即将处于DESTROYED状态的另一个LifecycleOwner都会收到数据回调,而这破坏了observe(LifecycleOwner,Observer)所期望的生命周期安全。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//限定只能在主线程调用 observe 方法
assertMainThread("observe");
//当 Lifecycle 已经处于 DESTROYED 状态时,此时进行 observe 是没有意义的,直接返回
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//根据传入参数构建一个新的代理 Observer
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//将 observer 作为 key,wrapper 作为 value 进行存储
//当 mObservers 不包含该 key 时,调用 putIfAbsent 会返回 null
//当 mObservers 已包含该 key 时,调用 putIfAbsent 不会存储 key-value,并会返回之前保存的 value
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
//走到此步,说明之前 LiveData 内部已经持有了 observer 对象,且该 observer 对象已经绑定了其它的 LifecycleOwner 对象
//此时直接抛出异常
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
//observer 之前已经传进来过了,此处直接返回
return;
}
owner.getLifecycle().addObserver(wrapper);
}
上面的代码使用到了LifecycleBoundObserver,它是抽象类ObserverWrapper的实现类。ObserverWrapper用于包装外部传进来的Observer对象,为子类定义好特定的抽象方法和共用逻辑,主要是提供了共用的状态分发函数。
private abstract class ObserverWrapper {
//外部传进来的对 LiveData 进行数据监听的 Observer
final Observer<? super T> mObserver;
//用于标记 mObserver 是否处于活跃状态
boolean mActive;
//用于标记 Observer 内最后一个被回调的 value 的新旧程度
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {