了解LiveData的内部原理需要关注以下几个问题:
- LiveData是如何添加观察者的?
- LiveData是如何感知生命周期并仅通知处于Active状态的观察者的?
- postValue和setValue的内部实现是什么?
- LiveData如何将数据改变通知给观察者(
dispatchingValue
方法内部实现)?
1. 添加观察者
示例代码
// observe 方法的第一个参数是 LifecycleOwner,第二个参数是观察者对象
mutableLiveData.observe(this, observer)
源码分析
observe
方法
LiveData
提供了 observe
方法来添加观察者。该方法需要传入两个参数:LifecycleOwner
和 Observer<T>
。以下是 observe
方法的源码解析:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
// 如果当前状态是 DESTROYED,直接 return
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
// 创建 LifecycleBoundObserver 包装类,并将 owner 和 observer 作为参数传入
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// 将 LiveData 中的观察者 observer 添加到 map 中
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null) {
return;
}
// 将 LifecycleBoundObserver 添加为 Lifecycle 的观察者
owner.getLifecycle().addObserver(wrapper);
}
在 observe
方法中:
- 创建
LifecycleBoundObserver
包装类,并将owner
和observer
作为参数传入。 - 将
LiveData
中的观察者observer
添加到mObservers
map 中。 - 将
LifecycleBoundObserver
添加为Lifecycle
的观察者,使得LiveData
能感知生命周期变化。
2. 感知生命周期
LifecycleBoundObserver
类
LifecycleBoundObserver
是 LiveData
的静态内部类,继承了 ObserverWrapper
并实现了 LifecycleEventObserver
接口。以下是 LifecycleBoundObserver
的关键实现:
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
/**
* 判断当前状态是否是 Active 的,Active 状态包括 STARTED 和 RESUMED 状态
*/
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
/**
* 当生命周期变化时,onStateChanged 方法会被调用
*/
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
// 如果当前状态是 DESTROYED,就移除观察者
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
// 如果活跃状态改变了,就调用 activeStateChanged 方法
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
在 LifecycleBoundObserver
中:
- 实现了
LifecycleEventObserver
接口:当生命周期变化时,onStateChanged
方法会被调用。 onStateChanged
:根据活跃状态是否改变,调用activeStateChanged
方法。activeStateChanged
:是父类ObserverWrapper
的方法,根据活跃状态是否是 Active,调用dispatchingValue
方法。
ObserverWrapper
类
ObserverWrapper
是观察者的包装类,activeStateChanged
方法在状态变化时调用 dispatchingValue
方法:
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
dispatchingValue(this);
}
}
}
在 ObserverWrapper
的 activeStateChanged
方法中,如果状态变为 Active
,就调用 LiveData
的 dispatchingValue
方法,参数为 ObserverWrapper
对象本身。dispatchingValue
方法负责分发数据和通知观察者。
3. postValue
和 setValue
方法内部实现
当 LiveData
调用 postValue
或 setValue
方法后,如果当前页面处于活跃状态,观察者就会收到通知。以下是 postValue
和 setValue
方法的源码:
protected void postValue(T value) {
boolean postTask;
// 使用锁保证多线程中数据的正确性
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
// 将任务调度到主线程执行
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
// postValue 方法将任务调度到主线程后,就会执行 run 方法
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
// 获取 postValue 设置的 value
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
// 然后调用 setValue 方法
setValue((T) newValue);
}
};
@MainThread
protected void setValue(T value) {
// 如果不是在主线程运行,则抛出 IllegalStateException 异常
assertMainThread("setValue");
// mVersion 同 mLastVersion 一起来标记数据是否发生改变
mVersion++;
// mData 就是 LiveData 中持有的被观察者数据,每次 setValue 方法被调用都会为其重新赋值
mData = value;
// 用于分发数据并通知观察者
// 在 LifecycleBoundObserver 中,观察到生命周期改变并且是活跃状态,也会调用该方法
dispatchingValue(null);
}
postValue
将任务切换到主线程,然后调用 setValue
方法。setValue
方法更新数据(为 mData
赋值)并调用 dispatchingValue
方法通知观察者。
4. 分发数据和通知观察者
在分析 LiveData 感知生命周期和 postValue
/setValue
方法内部的实现时,我们已经知道最终都会调用 dispatchingValue
来分发数据和通知观察者。
void dispatchingValue(@Nullable ObserverWrapper initiator) {
// 正在处于分发状态中
if (mDispatchingValue) {
// 标记当前分发无效,直接 return
mDispatchInvalidated = true;
return;
}
// 标记当前处于分发状态
mDispatchingValue = true;
do {
// 分发有效
mDispatchInvalidated = false;
// 如果是在 LifecycleBoundObserver 中,观察到生命周期改变并且是活跃状态,调用的本方法,
// initiator 就是 LifecycleBoundObserver 对象自身,不为 null。
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else { // 如果是 setValue 方法调用的本方法,initiator 为 null
// 从 map 集合中取出观察者对象的包装类,
for (Iterator<Map.Entry<Observer<? super T>, LiveData.ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
// 通知观察者
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
// 标记不处于分发状态
mDispatchingValue = false;
}
dispatchingValue
方法主要通过 mDispatchingValue
来标记是否处于分发状态。如果不处于分发状态,则会调用 considerNotify
方法通知观察者。considerNotify
方法源码如下:
private void considerNotify(ObserverWrapper observer) {
// 如果 ObserverWrapper 的 mActive 值不为 true,就直接 return
if (!observer.mActive) {
return;
}
// 如果当前 observer 对应组件的状态不是 Active
if (!observer.shouldBeActive()) {
// 就会再次调用 activeStateChanged 方法,并传入 false,
// 其方法内部会再次判断是否执行 onActive 方法和 onInactive 方法回调
observer.activeStateChanged(false);
return;
}
// mVersion 在何时会变化?
// postValue/setValue 的时候会改变 mVersion 的值
// 而只是生命周期状态改变并不会改变 mVersion 的值,所以不会通知观察者
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
// 如果判断条件都满足会调用 Observer 的 onChanged 方法,
// onChanged 正是使用 LiveData 的 observe 方法的回调
observer.mObserver.onChanged((T) mData);
}
considerNotify
进行了多次判断,如果是活跃状态才会调用观察者的 onChanged
方法通知观察者。这里需要注意的是 onChanged
方法的参数 mData
。mData
是在调用 setValue
方法后立即被赋值的,而 onChanged
方法只有在 Active 状态时才会被调用。因此,当页面处于后台时调用了多次 postValue
/setValue
方法,当页面重新回到前台,onChanged
只会调用一次,并且 mData
的值为最后一次 postValue
/setValue
的值。
总结
通过上述源码分析,我们了解了 LiveData 的工作原理,包括添加观察者、感知生命周期、postValue
和 setValue
的内部实现,以及数据分发和通知观察者的机制。LiveData 能够感知组件的生命周期变化并在适当的时机通知观察者,这使得它成为 Android 应用中处理数据和UI更新的一个重要工具。