一、LiveData 是什么
LiveData 本质上是一个具备“生命周期感知能力”的数据容器。它延续了观察者模式的基本思想,由 LiveData 作为被观察者,Activity 或 Fragment 作为观察者,在数据变化时接收通知并更新 UI。
它和普通观察者模式最大的不同在于:LiveData 并不会无条件地把更新推给所有订阅者,而是会结合宿主的生命周期状态决定是否分发数据。这让它天然适合 UI 场景,也避免了因页面销毁后仍然持有观察关系而导致的内存泄漏和空指针问题。
二、观察者模式的实现
LiveData 的基础架构建立在经典的观察者模式之上。当内部数据发生变化时,它会通知所有已注册的观察者执行更新逻辑。
2.1 核心角色与职责
- LiveData 内部持有一个泛型数据值,作为当前对外暴露的状态。
- 同时它也维护一组观察者,用于接收数据变化后的回调通知。
- 当开发者调用
observe()注册观察者后,这个观察关系就会被保存下来。 - 当业务侧调用
setValue()或postValue()更新数据时,LiveData 会触发分发流程,通知满足条件的观察者执行onChanged()。

2.2 数据分发为什么能驱动 UI 更新
从使用方式看,LiveData 很像一个“可被订阅的数据源”:
- ViewModel 更新数据。
- LiveData 持有新值。
- Activity / Fragment 作为观察者收到通知。
- UI 基于新值重新渲染。
因此,LiveData 的第一层价值并不是“生命周期感知”,而是先把“数据变化 -> UI 刷新”这条链路用观察者模式串起来。
三、生命周期感知是怎么实现的
如果只有观察者模式,开发者仍然需要在页面销毁时手动解绑,否则很容易留下失效引用。LiveData 真正有价值的地方,在于它把"观察关系是否有效"这件事交给了生命周期系统来自动判断。
下图展示了这套机制的完整链路,自上而下分为三层:

3.1 第一层:系统如何发出生命周期信号
生命周期事件的起点在系统侧。以 onPause 为例:主线程收到 handlePauseActivity 指令后,会依次调用 performPause() → onPause(),同时向 Application.ActivityLifecycleCallbacks 分发对应回调。
这是 Android 暴露给应用层的第一个公开出口——但它是全局广播式的,并不针对任何具体订阅者。
3.2 第二层:Activity 如何把事件传给 LifecycleRegistry
ComponentActivity(AppCompat 的基类)实现了 LifecycleOwner,内部持有一个 LifecycleRegistry。当 Activity 自身收到 onPause 等回调时,会立刻调用 LifecycleRegistry.handleLifecycleEvent(),把当前状态同步进去。
LifecycleRegistry 的作用是集中管理状态并按序分发:它维护着一份 observerMap,存放所有注册进来的 LifecycleObserver,一旦状态变化就逐一通知。
这一层解决的问题是:把散落在 Activity 各生命周期方法里的回调,统一变成一个可订阅的事件流,外部任何组件都可以通过 LifecycleRegistry 感知宿主状态,而不必直接持有 Activity 引用。
3.3 第三层:LiveData 如何利用这个事件流实现自动解绑
当调用 liveData.observe(lifecycleOwner, observer) 时,LiveData 并不会把 observer 直接存起来,而是将其包装成 LifecycleBoundObserver,然后把这个包装对象注册进 LifecycleRegistry。
LifecycleBoundObserver 同时扮演两个角色:
- 数据观察者:数据变化时收到
onChanged()回调,刷新 UI。 - 生命周期观察者:宿主状态变化时同步收到通知,据此决定是否允许分发。
具体行为如下:
- 宿主处于 STARTED / RESUMED(活跃态)→ 正常分发数据。
- 宿主进入 STOPPED(非活跃态)→ 暂停分发,更新暂存,等恢复活跃后补发。
- 宿主收到 ON_DESTROY →
LifecycleBoundObserver主动将自己从LifecycleRegistry中移除,彻底解绑,不再占用任何引用。
整条链路的核心逻辑:LiveData 不需要知道 Activity 的具体实现,只需订阅 LifecycleRegistry 的事件流,就能全自动地管理观察关系的有效期,开发者无需写任何 onDestroy 解绑代码。
四、总结
LiveData 的价值不只是“能通知界面刷新”,而是把两件事情合在了一起:
- 用观察者模式解决数据变化的分发问题。
- 用生命周期系统解决观察关系的有效期问题。
前者让它成为一个适合 UI 订阅的数据容器,后者让它在 Activity / Fragment 频繁销毁重建的场景下依然安全可用。这也是 LiveData 在 Jetpack 体系中长期被广泛采用的原因。