Android LiveData 原理完整剖析:从订阅、分发到粘性事件

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 递增 mVersionconsiderNotify 比较 observer.mLastVersionmVersion,只有 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,版本号检查就不会通过,粘性事件自然就不会触发了。

由于 mLastVersionObserverWrapper 的包级私有字段,需要通过反射来修改:

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 设为当前 mVersionconsiderNotify 检查 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 跨线程投递,连续调用丢中间值

相关推荐
为你学会写情书1 小时前
为什么弹窗状态不该放在全局Store?React性能优化面经复盘与实战指南
面试
众人皆醒我独醉1 小时前
什么是输入上下文、MCP、Agent、Skills?—— 四个让你用不好 AI 的概念,一次讲清楚
面试·ai编程
liang_jy13 小时前
文件管理(一)—— 初识文件管理
面试·操作系统
liang_jy14 小时前
文件管理(二)—— 文件结构
面试·操作系统
HeiSenBerg19 小时前
Android Lifecycle 原理完整剖析:从监听、事件分发到状态驱动
面试
CoderYanger19 小时前
A.每日一题:1979. 找出数组的最大公约数
java·程序人生·算法·leetcode·面试·职场和发展·学习方法
HeiSenBerg19 小时前
LeakCanary 原理完整剖析:从初始化到堆分析
面试
沉默王二20 小时前
腾讯面试官:“你说你做了一个终端Agent,那说说 LLM 和 Agent的区别,ReAct、MCP、Tool、Memory、Skills?”我信誓旦旦开始背了
面试·agent·腾讯
爱学习的执念21 小时前
软件测试面试常问,主要考察你对接口测试相关知识的掌握程度?
面试·职场和发展