LiveData 源码分析
LiveData 是 jetpack 包里的一个组件,这个组件主要的作用是作为一个可观察数据的持有者,它维护一个变量,可以注册监听者,然后再变量修改的时候通知监听者。
LiveData 只是一个很小的工具,在 MVVM 架构中,我们一般将 LiveData 对象放到 ViewModel 里,之后有时间会学习一下 ViewModel 的使用,这里先简单介绍一下 LiveData。
MutableLiveData
LiveData 是一个抽象类,我们一般使用它的的一个实现类 MutableLiveData,当然你自己实现一个实现类也是可以的,此处就以 MutableLiveData 为例子介绍。
构造
构造很简单,直接指定泛型并调用构造方法即可:
val liveData = MutableLiveData<String>()
val liveDataWithDefault = MutableLiveData<String>("default")
至此,我们就创建了一个 MutableLiveData 对象
方法
MutableLiveData 常用的有如下方法:
fun getValue():T?
fun setValue(value:T):Unit
fun postValue(value: T): Unit
fun observe(owner:LifecycleOwner, observer: Observer<T>):Unit
fun observeForever( observer: Observer<T>):Unit
fun removeObserve(observer: Observer<T>):Unit
总结
这里直接放出总结,之后是源码分析。
对于 getValue ,当 LiveData 还未指定值的时候会返回 null ,哪怕在 Kotlin 中指定泛型为非空,也会返回空。
对于 setValue 和 postValue ,两者都可以更新当前值并通知给观察者,前者只能运行在主线程,后者会主动切换回主线程,因此可以在任何线程调用,不过会产生并发问题(当调用 postValue 之后立即调用 getValue,值可能还没更新)。
对于 observe 和 observeForever ,两者都可以向 LiveData 添加观察者,前者与传入的 LifecycleOwner 有关,后者无关,只要值发送改变,就一定会接收到更新。
对于 observe 添加的观察者,具有如下特性:
- 当
LifecycleOwner当前周期为DESTROYED的时候,添加会失败,如果已经添加了,则会移除。 - 当
LifecycleOwner的周期为STARTED之后的时候,观察者才会为Active状态 - 当值发送改变的时候,只有
Active状态的观察者会更新 - 当
LifecycleOwner第一次由 非Active变为Active的时候,只要当前值不是NO_SET,都会通知观察者一次 - 当
LifecycleOwner第二次由 非Active变为Active的时候,如果在上次处于Active之间值更新过,则会通知观察者一次
获取当前值
获取当前值,我们可以调用 getValue 方法,不过在 Kotlin 中,会被自动转换为获取 value 成员变量,因此 Kotlin 中可以直接使用 liveData.value 去获取当前值,这里注意返回值类型,在 Kotlin 中类型是安全的,但是上面可以看到当我们指定泛型为 T 的时候,返回值是 T?,也就是永远不是空安全的。我们可以查看 getValue 方法的源码看出问题:
/**
* Returns the current value.
* Note that calling this method on a background thread does not guarantee that the latest
* value set will be received.
*
* @return the current value
*/
@SuppressWarnings("unchecked")
@Nullable
public T getValue() {
Object data = mData;
if (data != NOT_SET) {
return (T) data;
}
return null;
}
以上是 LiveData 里 getValue 的源码,因为使用的是 Java 所以返回值没有空安全检查,不过加入了 @Nullable 注解表明不是空安全的,因此如果在 Kotlin 语言中调用会返回 T?。
同时我们可以看到在 Kotlin 环境中当我们指定泛型为空安全时候返回 null 只有一种情况,就是当 data == NOT_SET 的时候,通过命名也可以猜出此时应该是我们调用无参构造方法,还未传入任何值的时候。
其实从 LiveData 的作用来看,我个人是不太建议调用 getValue 方法的,具体可以看下面内容。
更新值
更新值,有两个方法 setValue 和 postValue ,其实按照安卓的命名规律,光看名字都能猜出个大概,我们可以直接看源码:
/**
* Sets the value. If there are active observers, the value will be dispatched to them.
* <p>
* This method must be called from the main thread. If you need set a value from a background
* thread, you can use {@link #postValue(Object)}
*
* @param value The new value
*/
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
我们注意到这里有 MainThread 注解,还调用了一个 assertMainThread 方法,继续来到这个方法:
static void assertMainThread(String methodName) {
if (!ArchTaskExecutor.getInstance().isMainThread()) {
throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
+ " thread");
}
}
可以看到他会使用 ArchTaskExecutor 来检查当前是否为主线程,当不是主线程的时候会抛出异常,所以 setValue 只能在主线程调用。
此外,我们还注意到这里有一个 mVersion++ 的操作,这里涉及到一些 LiveData 的高级内容,下次有空再来讲解一波吧。
此外,Kotlin 会对 setXX 的方法进行转换,因此如果在 Kotlin 中,我们可以直接使用 liveData.value = "xx" 来调用 setValue 方法。
/**
* Posts a task to a main thread to set the given value. So if you have a following code
* executed in the main thread:
* <pre class="prettyprint">
* liveData.postValue("a");
* liveData.setValue("b");
* </pre>
* The value "b" would be set at first and later the main thread would override it with
* the value "a".
* <p>
* If you called this method multiple times before a main thread executed a posted task, only
* the last value would be dispatched.
*
* @param value The new value
*/
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
首先是一个同步锁,锁内将 mPendingData 的值设置为 value,并且如果 mPendingData 为 NOT_SET 的时候就使用 ArchTaskExecutor 在主线程运行一个 Runnable ,来看看这个 Runnable :
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
同样也是同步锁,这里将 mPendingData 恢复成 NOT_SET 并调用 setValue 方法,注意这个 Runnable 是运行在主线程中的,也就是说 postValue 可以运行在任意线程中,并且在连续多次调用的时候只有最后一次会生效,这是使用了 mPendingData 作为缓冲实现的,调用 postValue 的时候,只有当当前没有缓冲的时候才会将 Runnable 放入 ArchTaskExecutor 运行,在运行之前我们调用 postValue 的时候只会更新 mPendingData ,并不会执行 Runnable ,当 Runnable 执行中在将 mPendingData 恢复为 NOT_SET。
监听数据
这里是重点,因此作为一个一级标题,首先我们看看绑定观察者的方法,有两个:
fun observe(owner:LifecycleOwner, observer: Observer<T>):Unit
fun observeForever( observer: Observer<T>):Unit
来看看源码吧:
/**
* Adds the given observer to the observers list within the lifespan of the given
* owner. The events are dispatched on the main thread. If LiveData already has data
* set, it will be delivered to the observer.
* <p>
* The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED}
* or {@link Lifecycle.State#RESUMED} state (active).
* <p>
* If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will
* automatically be removed.
* <p>
* When data changes while the {@code owner} is not active, it will not receive any updates.
* If it becomes active again, it will receive the last available data automatically.
* <p>
* LiveData keeps a strong reference to the observer and the owner as long as the
* given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to
* the observer & the owner.
* <p>
* If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData
* ignores the call.
* <p>
* If the given owner, observer tuple is already in the list, the call is ignored.
* If the observer is already in the list with another owner, LiveData throws an
* {@link IllegalArgumentException}.
*
* @param owner The LifecycleOwner which controls the observer
* @param observer The observer that will receive the events
*/
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
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);
}
注解有点长哈,内容其实不多,首先是确保在主线程调用,接下来就检查一下 LifecycleOwner 的生命周期,如果是 DESTROYED 的时候添加失败,后面就是将 observer 保存起来,同时我们看到最后在 LifecycleOwner 中添加了一个 warpper 对象,我们进入 LifecycleBoundObserver 看看:
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
比较重要的有两个方法:
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
/*省略,接下来会讲到*/
}
shouldBeActive 后面会讲到,主要来看 onStateChanged ,这是继承的 LifecycleEventObserver 的方法,并且刚刚也看到它监听了 owner ,其实内容也不难理解,就是当 LifecycleOwner 变为 DESTROYED 的时候移除观察者,这也不难理解,就是在组件被销毁的时候自动移除观察者。
其实对于使用 observe 绑定的观察者,它的特性会与传入的 owner 绑定,主要体现为两点:
- 当
owner为DESTROYED的时候,无法添加观察则,当owner变为DESTROYED的时候移除观察者: - 只有当
owner处于某些特定生命周期的时候,观察者才会接收到数据监听,并且当owner从某些生命周期变为某些生命周期的时候,哪怕数据没发生更新,也会调用观察者,这点将在之后进行说明:
接下来看看 observeForever
/**
* Adds the given observer to the observers list. This call is similar to
* {@link LiveData#observe(LifecycleOwner, Observer)} with a LifecycleOwner, which
* is always active. This means that the given observer will receive all events and will never
* be automatically removed. You should manually call {@link #removeObserver(Observer)} to stop
* observing this LiveData.
* While LiveData has one of such observers, it will be considered
* as active.
* <p>
* If the observer was already added with an owner to this LiveData, LiveData throws an
* {@link IllegalArgumentException}.
*
* @param observer The observer that will receive the events
*/
@MainThread
public void observeForever(@NonNull Observer<? super T> observer) {
assertMainThread("observeForever");
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
可以看到内容其实差不多,不过 wrapper 对象变为了 AlwaysActiveObserver,同样来看看:
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer<? super T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
这个就简单多了,可以看到 shouldBeActive 永远返回 true ,同时也没有和 LifecycleOwner 绑定,事实上,通过 observeForever 绑定的观察者,只要数据发生变化就一定会通知,对于这种观察者,我们只能调用 removeObserver 来移除这种观察者。
数据监听
来看看 LiveData 是如何通知观察者的,因为 postValue 之后也是调用 setValue 方法,所以我们还是回到 setValue 方法的源码:
/**
* Sets the value. If there are active observers, the value will be dispatched to them.
* <p>
* This method must be called from the main thread. If you need set a value from a background
* thread, you can use {@link #postValue(Object)}
*
* @param value The new value
*/
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
可以看到有一个 dispatchingValue 方法,我们来看看:
@SuppressWarnings("WeakerAccess") /* synthetic access */
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
主要是这里通过迭代器遍历观察者的 map 然后来到了 considerNotify 方法:
@SuppressWarnings("unchecked")
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
可以看到,只有 observer.shouldBeActive() 返回 true 才会通知,还记得刚刚的两种观察者吗,对于 observeForever 绑定的观察者,这里永远会是 true ,而对于 observe 绑定的观察者,可以看到:
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
只有当 LifecycleOwner 当前状态在 STARTED 之后的时候才会调用,例如在 Activity 里,只有在 onStart 之后,onStop 之前观察者才会有效。
实际上,不止这时候有效,在刚刚的 LifecycleBoundObserver 的 onStatusChange 方法中,还做了一些特殊处理,这部分源码分析起来比较麻烦,因此我这里直接放结论了,就在之前总结之中。