Android LiveData 原理完整剖析:从订阅、分发到粘性事件
LiveData 的核心逻辑其实非常简洁------维护一个数据 + 一组观察者,数据变化时通知观察者------但围绕"生命周期感知"和"粘性事件"这两个特性,做了精巧的设计。
本文从源码层面,把 LiveData 的完整工作流程讲清楚。
一、整体架构
LiveData 系统由以下几个核心部分组成:
yaml
LiveData<T>
├─ mData: T 当前持有的数据
├─ mVersion: int 数据版本号(每次 setValue 递增)
├─ mActiveCount: int 活跃观察者计数
├─ mObservers: SafeIterableMap 所有观察者
│
└─ ObserverWrapper(包装类)
├─ LifecycleBoundObserver(observe 添加的)
└─ AlwaysActiveObserver(observeForever 添加的)
关键角色:
| 角色 | 说明 |
|---|---|
| LiveData | 核心类,持有数据和观察者列表 |
| ObserverWrapper | 观察者的包装类,记录活跃状态、版本号 |
| LifecycleBoundObserver | 继承 ObserverWrapper + LifecycleEventObserver,绑定了生命周期 |
| SafeIterableMap | 支持遍历过程中安全增删操作的 Map |
| mVersion | 数据版本号,每次 setValue 递增 |
| mLastVersion | 每个观察者自己的版本号,记录它最后一次收到的数据版本 |
二、添加观察者:observe()
java
// LiveData.java --- observe()
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
// ★ 必须在主线程调用
assertMainThread("observe");
// ★ 如果 LifecycleOwner 已经是 DESTROYED 状态,直接忽略
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
// ★ 包装 Observer:LifecycleBoundObserver
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// ★ 存入观察者列表(putIfAbsent --- 相同 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;
}
// ★ 关键:把 LifecycleBoundObserver 注册到 LifecycleOwner
owner.getLifecycle().addObserver(wrapper);
}
2.1 LifecycleBoundObserver
java
// LiveData.java --- 内部类
class LifecycleBoundObserver extends ObserverWrapper
implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
// ★ 判断是否活跃:至少 STARTED(onStart 之后,onPause 之前)
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
// ★ LifecycleEventObserver 接口 --- 生命周期变化时回调
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
// 如果变为 DESTROYED → 直接移除 Observer
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
// ★ while 循环:activeStateChanged 内部可能触发 dispatchingValue
// 而 dispatchingValue 中 observer 的回调可能再次改变生命周期
// 循环直到状态稳定
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
}
2.2 ObserverWrapper
java
private abstract class ObserverWrapper {
final Observer<? super T> mObserver; // 真正的观察者
boolean mActive; // 是否活跃
int mLastVersion = START_VERSION; // 该观察者最后收到的版本号(初始 = -1)
abstract boolean shouldBeActive();
void activeStateChanged(boolean newActive) {
if (newActive == mActive) return;
mActive = newActive;
// ★ 更新全局活跃计数
changeActiveCounter(mActive ? 1 : -1);
// ★ 如果变为活跃 → 立即分发最新数据
if (mActive) {
dispatchingValue(this);
}
}
}
三、添加观察者:observeForever()
java
@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 LifecycleBoundObserver) {
throw new IllegalArgumentException(
"Cannot add the same observer with different lifecycles");
}
if (existing != null) return;
// ★ 直接设为活跃(不依赖生命周期)
wrapper.activeStateChanged(true);
}
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer<? super T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true; // ★ 永远活跃
}
}
observe() vs observeForever():
| observe() | observeForever() | |
|---|---|---|
| 生命周期感知 | ✅ 自动跟随 LifecycleOwner | ❌ 永远活跃 |
| 自动移除 | ✅ DESTROYED 时自动移除 | ❌ 必须手动 removeObserver |
| 粘性事件 | ✅ 第一次变为活跃时触发 | ✅ 注册时立即触发 |
四、setValue() 和 postValue()
setValue()
java
@MainThread
protected void setValue(T value) {
assertMainThread("setValue"); // 必须在主线程
mVersion++; // ★ 版本号递增
mData = value; // 更新数据
dispatchingValue(null); // ★ 分发给所有活跃观察者
}
postValue()
java
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = (mPendingData == NOT_SET);
mPendingData = value;
}
if (postTask) {
// ★ 向主线程抛 Runnable
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue); // ★ 最终调到 setValue
}
};
连续 postValue 两次会丢中间值:
ini
postValue(A) → postTask=true → post Runnable
postValue(B) → postTask=false → 只覆盖 mPendingData = B
Runnable 执行 → setValue(B) → A 被跳过了
五、事件分发:dispatchingValue()
java
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
// ★ 正在分发中 → 标记需要重新分发
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
// ★ 分发给指定观察者(来自 activeStateChanged)
considerNotify(initiator);
initiator = null;
} else {
// ★ 分发给所有观察者(来自 setValue)
for (Iterator<...> iterator = mObservers.iteratorWithAdditions();
iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break; // 有新数据 → 重新循环
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
双模式:
| 谁调 dispatchingValue | initiator | 分发范围 |
|---|---|---|
| activeStateChanged(true) | 这个 observer | 只分发给这一个 |
| setValue() | null | 所有观察者 |
六、considerNotify
每个观察者在收到回调前,要过三个检查:
java
private void considerNotify(ObserverWrapper observer) {
// ★ 检查 1:必须活跃
if (!observer.mActive) {
return;
}
// ★ 检查 2:二次确认 LifecycleOwner 真的活跃
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false); // 强制设为不活跃
return;
}
// ★ 检查 3:观察者版本号 < 数据版本号?
// mLastVersion >= mVersion → 数据已是最新,不分发
if (observer.mLastVersion >= mVersion) {
return;
}
// ★ 更新版本号 + 回调
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
三个条件必须全部通过,observer 才会收到回调。
七、版本号机制与粘性事件的产生
java
static final int START_VERSION = -1;
private int mVersion = START_VERSION;
版本号是控制分发的核心。 每次 setValue 递增 mVersion。considerNotify 比较 observer.mLastVersion 与 mVersion,只有 mLastVersion < mVersion 时才会分发。
粘性事件是怎么产生的
当 addObserver 调用 owner.getLifecycle().addObserver(wrapper) 时,Lifecycle 会立即回调 onStateChanged,传入当前状态。
如果当前状态 >= STARTED,shouldBeActive() 返回 true,触发:
scss
activeStateChanged(true)
→ dispatchingValue(this)
→ considerNotify(wrapper)
→ 新 Observer 的 mLastVersion = -1
→ 数据 mVersion >= 0(只要有 setValue 过)
→ mLastVersion(-1) < mVersion(>=0) → 版本号检查通过
→ observer.onChanged(data) ← 注册时立即收到最新值!
粘性事件的本质:新 Observer 的 mLastVersion = -1,而数据 mVersion >= 0,所以第一次版本号检查必然通过。
粘性事件什么时候触发
取决于注册时的 Lifecycle 状态:
scss
Activity.onCreate() 中 observe:
→ Lifecycle 状态 = CREATED
→ shouldBeActive() = CREATED.isAtLeast(STARTED) = false
→ mActive = false
→ ★ 不分发,粘性事件不触发
→ 等 onStart 之后,Lifecycle 变为 STARTED
→ onStateChanged 被回调
→ shouldBeActive() = true
→ activeStateChanged(true)
→ dispatchingValue(this)
→ ★ 粘性事件在此触发
Activity.onResume() 中 observe:
→ Lifecycle 状态 = RESUMED
→ shouldBeActive() = true
→ activeStateChanged(true)
→ ★ 粘性事件立即触发
Activity.onStop() 中 observe:
→ Lifecycle 状态 = CREATED
→ shouldBeActive() = false
→ mActive = false
→ ★ 粘性事件不触发
→ 等下次 onStart 才触发
结论:粘性事件不是在 observe() 调用时触发的,而是 Observer 第一次变为活跃时触发的。
粘性事件的工作流程
scss
初始状态:
mVersion = -1
观察者 A 注册:mLastVersion = -1
setValue("Hello") → mVersion = 0
→ A.mLastVersion(-1) < mVersion(0) → 分发 → A.onChanged("Hello")
→ A.mLastVersion = 0
新观察者 B 注册(onResume 中):
B.mLastVersion = -1
变为活跃 → dispatchingValue(B)
→ B.mLastVersion(-1) < mVersion(0) → 分发 → B.onChanged("Hello")
★ 粘性事件
为什么后台回前台不会重复分发
scss
Activity 进入后台(onStop)→ mActive = false
后台 setValue("World") → mVersion = 1,但 observer 不活跃 → 不分发
Activity 回到前台(onStart)→ mActive = true
→ dispatchingValue(this)
→ considerNotify
→ mLastVersion(0) < mVersion(1) → 分发 → onChanged("World")
→ mLastVersion = 1
但如果后台期间多次 setValue:
→ setValue("World") → mVersion = 1
→ setValue("!!!") → mVersion = 2
回到前台
→ mLastVersion(0) < mVersion(2) → 分发 → onChanged("!!!")
→ "World" 被跳过了(但 mData 始终是最新的 "!!!")
八、粘性事件的解决办法
粘性事件在某些场景下是需要的(如页面初始化显示已有数据),但在另一些场景下是不希望发生的(如弹出 Toast、Snackbar、页面导航)。
源头阻止分发(反射修改 mLastVersion)
粘性事件的本质是 considerNotify 中的版本号检查:
java
if (observer.mLastVersion >= mVersion) {
return; // 不分发
}
如果能在 Observer 注册后、变为活跃前,把 mLastVersion 改成等于当前 mVersion,版本号检查就不会通过,粘性事件自然就不会触发了。
由于 mLastVersion 是 ObserverWrapper 的包级私有字段,需要通过反射来修改:
java
public class UnpeekLiveData {
// ★ 通过反射将 Observer 的 mLastVersion 设置为当前 mVersion
public static <T> void observeNoSticky(
LiveData<T> liveData, LifecycleOwner owner, Observer<? super T> observer) {
// 先注册
liveData.observe(owner, observer);
try {
// ★ 反射获取 LiveData 的 mObservers 字段
Field observersField = LiveData.class.getDeclaredField("mObservers");
observersField.setAccessible(true);
// mObservers 是 SafeIterableMap
Object observers = observersField.get(liveData);
// ★ 从 mObservers 中取出当前 observer 对应的 ObserverWrapper
Method getMethod = observers.getClass().getDeclaredMethod("get", Object.class);
getMethod.setAccessible(true);
Object observerWrapper = getMethod.invoke(observers, observer);
// ★ 反射设置 mLastVersion
Field lastVersionField = observerWrapper.getClass()
.getSuperclass().getDeclaredField("mLastVersion");
lastVersionField.setAccessible(true);
// 获取当前 mVersion
Field versionField = LiveData.class.getDeclaredField("mVersion");
versionField.setAccessible(true);
int currentVersion = versionField.getInt(liveData);
// ★ 把 ObserverWrapper 的 mLastVersion 设为当前 mVersion
lastVersionField.set(observerWrapper, currentVersion);
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用:
kotlin
// 不粘性的 observe
UnpeekLiveData.observeNoSticky(viewModel.toastMessage, this) { msg ->
showToast(msg) // ★ 只有注册后的新事件触发,不会收到旧数据
}
原理: 注册后立即通过反射把 Observer 的 mLastVersion 设为当前 mVersion。considerNotify 检查 mLastVersion >= mVersion 为 true,跳过分发。此后新的 setValue 会递增 mVersion,所以后续事件可以正常触发。
九、完整时序
scss
时间轴 Activity LifecycleRegistry LiveData Observer
│ │ │ │ │
│ onCreate │ │ │ │
│──────────▶│ │ │ │
│ │ observe(owner, obs)│ │ │
│ │───────────────────▶│ │ │
│ │ │ addObserver(wrapper)│ │
│ │ │───────────────────▶│ │
│ │ │ │ │
│ │ onStateChanged(CREATED) │ │
│ │◀────────────────────────────────────────│ │
│ │ shouldBeActive() = false │ │
│ │ activeStateChanged(false) │ │
│ │ → mActive = false │ │
│ │ → 不分发 │ │
│ │ │ │ │
│ onStart │ │ │ │
│──────────▶│ │ │ │
│ │ onStateChanged(STARTED) │ │
│ │◀────────────────────────────────────────│ │
│ │ shouldBeActive() = true │ │
│ │ activeStateChanged(true) │ │
│ │ dispatchingValue(this) │ │
│ │─────────────────────────────────────────▶│ │
│ │ │ │ considerNotify() │
│ │ │ │ mLastVer(-1) < mVer │
│ │ │ │──────────▶─────────▶│
│ │ │ │ onChanged│
│ │ │ │◀────────────────────│
│ │ │ │ │
│ setValue │ │ │ │
│──────────▶│ │ │ │
│ │ │ mVersion++ │ │
│ │ │ mData = newValue │ │
│ │ │ dispatchingValue() │ │
│ │ │───────────────────▶│ │
│ │ │ │ considerNotify() │
│ │ │ │ mLastVer < mVersion│
│ │ │ │──────────▶─────────▶│
│ │ │ │ onChanged│
│ │ │ │◀────────────────────│
│ │ │ │ │
│ onStop │ │ │ │
│──────────▶│ │ │ │
│ │ onStateChanged(CREATED) │ │
│ │◀────────────────────────────────────────│ │
│ │ shouldBeActive() = false │ │
│ │ activeStateChanged(false) │ │
│ │ → mActive = false │ │
│ │ │ │ │
│ postValue │ │ │ │
│──────────▶│ │ │ │
│ │ │ mVersion++ (但 │ │
│ │ │ mActive=false → │ │
│ │ │ 不分发) │ │
│ │ │ │ │
│ onStart │ │ │ │
│──────────▶│ │ │ │
│ │ onStateChanged(STARTED) │ │
│ │◀────────────────────────────────────────│ │
│ │ shouldBeActive() = true │ │
│ │ activeStateChanged(true) │ │
│ │ dispatchingValue(this) │ │
│ │─────────────────────────────────────────▶│ │
│ │ │ │ mLastVer < mVersion│
│ │ │ │ → onChanged │
│ │ │ │──────────▶─────────▶│
│ │ │ │ │
│ onDestroy │ │ │ │
│──────────▶│ │ │ │
│ │ onStateChanged(DESTROYED) │ │
│ │◀────────────────────────────────────────│ │
│ │ │ removeObserver() │ │
│ │ │───────────────────▶│ │
十、完整类关系
scala
LiveData<T>
├─ mData: T
├─ mVersion: int (初始 -1)
├─ mActiveCount: int
├─ mPendingData: Object
├─ mDispatchingValue: boolean
├─ mDispatchInvalidated: boolean
├─ mObservers: SafeIterableMap<Observer, ObserverWrapper>
│
├─ observe(owner, observer)
├─ observeForever(observer)
├─ removeObserver(observer)
├─ setValue(value) @MainThread
├─ postValue(value) (任意线程)
├─ getValue(): T
│
├─ dispatchingValue(initiator)
├─ considerNotify(wrapper)
├─ changeActiveCounter(delta)
├─ onActive()
└─ onInactive()
abstract class ObserverWrapper
├─ mObserver: Observer<T>
├─ mActive: boolean
├─ mLastVersion: int
├─ shouldBeActive(): abstract
└─ activeStateChanged(newActive)
class LifecycleBoundObserver extends ObserverWrapper
implements LifecycleEventObserver
├─ mOwner: LifecycleOwner
└─ shouldBeActive() → isAtLeast(STARTED)
class AlwaysActiveObserver extends ObserverWrapper
└─ shouldBeActive() → true
十一、总结
一句话流程
observe()将 Observer 包装成 LifecycleBoundObserver 并注册到 Lifecycle。Lifecycle 回调使其变为活跃时触发一次数据分发(粘性事件)。后续setValue()递增版本号、更新数据、遍历所有观察者、检查版本号后回调。非活跃时不收数据,重新活跃时根据版本号决定是否重复分发。
关键设计点
| 设计 | 作用 |
|---|---|
| mVersion + mLastVersion | 版本号对比实现粘性事件 + 避免重复分发 |
| LifecycleBoundObserver | 通过 Lifecycle 感知生命周期,自动管理活跃状态 |
| dispatchingValue 双模式 | initiator != null 只发一个,null 发全部 |
| mDispatchInvalidated | 防止并发设置导致数据丢失 |
| mActiveCount | 从 0 到 1 调 onActive,从 1 到 0 调 onInactive |
| mPendingData + postToMainThread | postValue 跨线程投递,连续调用丢中间值 |