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
方法中,还做了一些特殊处理,这部分源码分析起来比较麻烦,因此我这里直接放结论了,就在之前总结之中。