Android Lifecycle 源码深度解析:状态机设计与事件分发机制
1. 为什么 Lifecycle 值得单独拎出来讲做 Android 开发的人迟早会撞上生命周期这个坎。Activity 和 Fragment 的生命周期回调就像一把双刃剑——用好了是秩序用不好就是灾难。我见过太多项目里网络请求的回调在 Activity 销毁后还在往 UI 上写数据播放器在后台还在跑Presenter 持有着已经死掉的 View 引用。这些问题的根源都指向同一个东西生命周期感知能力的缺失。Lifecycle 组件是 Android Jetpack 里最基础、也最容易被低估的一个。它做的事情说起来很简单——把生命周期这个概念从 Activity/Fragment 的私有回调里抽出来变成一个可以被任意对象观察的状态机。但就是这么一层抽象撑起了后面 ViewModel、LiveData、LifecycleService、ProcessLifecycleOwner 等一大票组件的底层逻辑。你如果没把 Lifecycle 吃透后面学 LiveData 的自动解绑、ViewModel 的存活范围、协程的 repeatOnLifecycle都只能停留在会用的层面出了问题根本不知道怎么排查。这篇文章我打算从源码结构、状态机设计、事件分发机制、注解处理器、实际落地场景几个角度把 Lifecycle 拆开揉碎讲一遍。适合已经用过 Lifecycle 但没看过源码的 Android 开发者也适合想搞清楚为什么 LiveData 能自动感知生命周期这类问题的同学。我会尽量把源码路径、关键类、核心方法都标出来方便你对着 AndroidX 的源码一起看。2. Lifecycle 的整体设计与核心思路拆解2.1 从回调地狱到观察者模式的演进在没有 Lifecycle 之前我们是怎么处理生命周期相关逻辑的最典型的写法是在 Activity 的 onResume 里启动某个组件在 onPause 里停止它。比如一个定位管理器Override protected void onResume() { super.onResume(); locationManager.start(); } Override protected void onPause() { super.onPause(); locationManager.stop(); }这种写法的问题在于调用方Activity和被调用方LocationManager之间形成了强耦合。LocationManager 完全不知道自己的 start 和 stop 应该对应哪个生命周期节点全靠 Activity 手动调度。一旦项目里有十几个这样的组件Activity 的每个生命周期方法都会变成一坨调度代码而且极易漏写。Lifecycle 的核心思路就是把这个调度关系反转过来让组件自己去订阅生命周期而不是让 Activity 去通知组件。Activity 只需要把自己的生命周期状态暴露出去谁关心谁就来注册观察者。这就是典型的观察者模式只不过被观察的对象是生命周期本身。2.2 三个核心抽象Owner、Observer、RegistryLifecycle 的源码结构其实非常精简核心就三个东西LifecycleOwner生命周期持有者任何想暴露生命周期的类都可以实现这个接口。Activity、Fragment 在 AndroidX 里都已经默认实现了它。LifecycleObserver生命周期观察者一个空接口具体的事件通过OnLifecycleEvent注解或者DefaultLifecycleObserver接口来接收。LifecycleRegistryLifecycle 的唯一实现类负责管理所有 Observer 的注册、状态同步和事件分发。这三者的关系可以用一句话概括LifecycleOwner 持有一个 LifecycleRegistryObserver 注册到 Registry 上Registry 在 Owner 生命周期变化时把事件分发给所有 Observer。为什么这么设计因为 Lifecycle 本身是个抽象类它只定义了addObserver、removeObserver、getCurrentState这几个方法真正的实现逻辑全部放在 LifecycleRegistry 里。这样做的好处是解耦——Owner 不需要关心分发逻辑Registry 也不需要关心 Owner 是谁双方只通过 Lifecycle 这个抽象类交互。2.3 状态与事件的双轨设计Lifecycle 里最容易让人绕晕的就是状态和事件这两个概念。很多人第一次看源码会疑惑为什么既有 State 又有 Event它们不是重复了吗其实不是。State 是静态快照Event 是动态迁移。Lifecycle 定义了五个状态状态含义INITIALIZED初始化完成还没收到任何生命周期回调CREATEDonCreate 之后或者 onStop 之后STARTEDonStart 之后或者 onPause 之后RESUMEDonResume 之后处于前台可见可交互DESTROYEDonDestroy 之后生命周期终结对应的事件有七个ON_CREATE、ON_START、ON_RESUME、ON_PAUSE、ON_STOP、ON_DESTROY以及一个特殊的 ON_ANY。状态和事件的关系是事件驱动状态迁移。比如当前状态是 CREATED收到 ON_START 事件后迁移到 STARTED当前状态是 STARTED收到 ON_STOP 事件后回退到 CREATED。这种设计让 Lifecycle 可以精确地表达我现在处于哪个阶段而不只是刚刚发生了什么。注意CREATED 状态对应两个不同的时机——onCreate 之后和 onStop 之后。这是很多人踩坑的地方。如果你在 Observer 里判断state CREATED要意识到它可能是刚创建也可能是已经停止。3. 核心源码细节与关键实现解析3.1 LifecycleRegistry 的注册与状态同步先看addObserver方法。它的逻辑大致是这样的public void addObserver(LifecycleObserver observer) { State initialState mState DESTROYED ? DESTROYED : INITIALIZED; ObserverWithState statefulObserver new ObserverWithState(observer, initialState); ObserverWithState previous mObserverMap.putIfAbsent(observer, statefulObserver); if (previous ! null) { return; // 已经注册过直接返回 } // 如果正在分发事件先缓存起来 if (mAddingObserverCounter ! 0 || mHandlingEvent) { return; } // 把新 Observer 的状态同步到当前 Owner 的状态 State targetState mState; while (statefulObserver.mState.compareTo(targetState) 0 mObserverMap.contains(observer)) { statefulObserver.dispatchEvent(mLifecycleOwner, upEvent(statefulObserver.mState)); statefulObserver.mState upEvent(statefulObserver.mState).getTargetState(); } }这段代码里有两个关键点值得展开。第一新注册的 Observer 会被追平到当前状态。假设 Activity 已经走到 RESUMED此时你才注册一个 Observer它不会只收到后续的事件而是会依次收到 ON_CREATE、ON_START、ON_RESUME 三个事件把状态补齐到 RESUMED。这个机制保证了 Observer 无论何时注册都能拿到完整的生命周期序列不会因为注册晚而漏掉前面的状态。第二分发过程中的重入保护。mAddingObserverCounter和mHandlingEvent这两个标志位是为了防止在事件分发过程中再次触发注册或分发导致状态错乱。这是并发场景下的经典处理手法用计数器而不是简单的布尔值是因为分发可能嵌套。3.2 事件分发的核心sync 与 forwardPassLifecycleRegistry 最核心的方法是sync()它在handleLifecycleEvent里被调用public void handleLifecycleEvent(Lifecycle.Event event) { State next getStateAfter(event); moveToState(next); } private void moveToState(State next) { if (mState next) { return; } mState next; if (mHandlingEvent || mAddingObserverCounter ! 0) { mNewEventOccurred true; return; } mHandlingEvent true; sync(); mHandlingEvent false; }sync()的逻辑是判断当前状态和目标状态谁大谁小如果当前状态落后就执行forwardPass()正向分发如果超前就执行backwardPass()反向分发。private void sync() { LifecycleOwner lifecycleOwner mLifecycleOwner.get(); if (lifecycleOwner null) { throw new IllegalStateException(LifecycleOwner is garbage collected); } while (!isSynced()) { mNewEventOccurred false; if (mState.compareTo(mObserverMap.eldest().getValue().mState) 0) { backwardPass(lifecycleOwner); } if (!mObserverMap.isEmpty()) { EntryLifecycleObserver, ObserverWithState newest mObserverMap.newest(); if (!mNewEventOccurred newest ! null mState.compareTo(newest.getValue().mState) 0) { forwardPass(lifecycleOwner); } } } mNewEventOccurred false; }这里有个很巧妙的设计Observer 的状态可能不一致。因为注册时机不同有的 Observer 可能还停在 CREATED有的已经到 RESUMED。sync()会不断循环直到所有 Observer 的状态都和 Owner 的当前状态对齐。mObserverMap用的是FastSafeIterableMap它支持在遍历过程中安全地增删元素这也是为什么能在分发过程中处理新注册的 Observer。3.3 ObserverWithState 与事件适配每个注册的 Observer 都会被包装成ObserverWithStatestatic class ObserverWithState { State mState; LifecycleEventObserver mLifecycleObserver; ObserverWithState(LifecycleObserver observer, State initialState) { mLifecycleObserver Lifecycling.lifecycleEventObserver(observer); mState initialState; } void dispatchEvent(LifecycleOwner owner, Event event) { State newState event.getTargetState(); mState min(mState, newState); mLifecycleObserver.onStateChanged(owner, event); mState newState; } }注意mState min(mState, newState)这一行。它的作用是如果 Observer 当前状态比事件目标状态还靠前就不更新状态。这是为了防止状态回退时出现异常。比如一个 Observer 已经在 RESUMED突然收到 ON_CREATE 事件理论上不该发生它的状态不会被错误地拉回到 CREATED。Lifecycling.lifecycleEventObserver()这个方法负责把各种形式的 Observer 统一转换成LifecycleEventObserver。它支持三种形式直接实现LifecycleEventObserver接口的实现DefaultLifecycleObserver接口的通过FullLifecycleObserverAdapter适配使用OnLifecycleEvent注解的通过ReflectiveGenericLifecycleObserver或生成的ClassesInfoCache适配3.4 注解处理器的编译期优化早期版本里OnLifecycleEvent注解是通过反射来调用的性能很差。后来 AndroidX 引入了注解处理器LifecycleProcessor在编译期生成一个LifecycleObserver的实现类把反射调用变成直接方法调用。生成的类名规则是原类名_LifecycleAdapter比如你写了一个MyObserver编译后会生成MyObserver_LifecycleAdapter。它内部持有一个MyObserver实例在onStateChanged里根据事件类型直接调用对应的方法public class MyObserver_LifecycleAdapter implements LifecycleEventObserver { final MyObserver mReceiver; MyObserver_LifecycleAdapter(MyObserver receiver) { this.mReceiver receiver; } Override public void onStateChanged(LifecycleOwner owner, Lifecycle.Event event) { if (event Lifecycle.Event.ON_CREATE) { mReceiver.onCreate(owner); } // ... 其他事件 } }Lifecycling在运行时通过Class.forName查找这个生成的类如果找到就用它找不到才回退到反射。这个优化让注解方式的性能提升了数倍也是为什么现在官方推荐用DefaultLifecycleObserver而不是注解——接口方式连生成的适配类都不需要直接调用。4. 实操落地从零接入 Lifecycle4.1 依赖配置与基础接入在build.gradle里加上依赖dependencies { def lifecycle_version 2.6.2 implementation androidx.lifecycle:lifecycle-runtime:$lifecycle_version implementation androidx.lifecycle:lifecycle-common-java8:$lifecycle_version // 如果需要 ViewModel 和 LiveData implementation androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version implementation androidx.lifecycle:lifecycle-livedata:$lifecycle_version }lifecycle-common-java8这个包提供了DefaultLifecycleObserver接口如果你的minSdk在 24 以上建议直接用它比注解方式更高效。写一个最简单的 Observerpublic class LocationObserver implements DefaultLifecycleObserver { private static final String TAG LocationObserver; Override public void onStart(NonNull LifecycleOwner owner) { Log.d(TAG, 开始定位); // 启动定位逻辑 } Override public void onStop(NonNull LifecycleOwner owner) { Log.d(TAG, 停止定位); // 停止定位逻辑 } }在 Activity 里注册public class MainActivity extends AppCompatActivity { private LocationObserver locationObserver new LocationObserver(); Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getLifecycle().addObserver(locationObserver); } }就这么几行定位逻辑就自动跟着 Activity 的生命周期走了。不需要在 onStart/onStop 里手动调用也不会漏掉。4.2 自定义 LifecycleOwner有时候我们需要给非 Activity/Fragment 的类赋予生命周期能力比如一个自定义的 View 或者一个业务管理器。这时候可以实现LifecycleOwner接口public class MyCustomView extends View implements LifecycleOwner { private final LifecycleRegistry lifecycleRegistry; public MyCustomView(Context context) { super(context); lifecycleRegistry new LifecycleRegistry(this); lifecycleRegistry.setCurrentState(Lifecycle.State.INITIALIZED); } Override public Lifecycle getLifecycle() { return lifecycleRegistry; } Override protected void onAttachedToWindow() { super.onAttachedToWindow(); lifecycleRegistry.setCurrentState(Lifecycle.State.STARTED); } Override protected void onDetachedFromWindow() { lifecycleRegistry.setCurrentState(Lifecycle.State.DESTROYED); super.onDetachedFromWindow(); } }这里有个关键点LifecycleRegistry 的构造需要传入 LifecycleOwner而且内部持有的是弱引用。这是为了防止 Observer 持有 Owner 导致内存泄漏。如果你在自定义 Owner 里忘记调用setCurrentStateObserver 就永远收不到事件。提示setCurrentState和handleLifecycleEvent的区别在于前者是直接设置状态会触发状态同步后者是通过事件驱动状态迁移。自定义 Owner 一般用setCurrentState更直观。4.3 在 ViewModel 中感知生命周期ViewModel 本身不是 LifecycleOwner但它可以通过LifecycleOwner参数来感知生命周期。比如在 ViewModel 里启动一个协程需要在 onDestroy 时取消public class MyViewModel extends ViewModel { private Job job; public void startTask(LifecycleOwner owner) { job viewModelScope.launch { owner.getLifecycle().currentStateFlow.collect { state - if (state Lifecycle.State.DESTROYED) { cancel() } } }; } }不过更推荐的做法是用repeatOnLifecycle它是 Lifecycle 2.4 之后引入的协程扩展能在生命周期进入 STARTED 时启动协程进入 STOPPED 时自动取消lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { // 这个块里的代码只在 STARTED 及以上状态执行 // 进入 STOPPED 时自动取消回到 STARTED 时重新启动 viewModel.uiState.collect { state - updateUI(state) } } }这个 API 是 Lifecycle 组件在协程时代最重要的扩展之一它解决了在后台收集 Flow 导致资源浪费的问题。5. 常见问题与排查技巧实录5.1 Observer 收不到事件怎么办这是最常见的问题。排查思路按顺序走第一步确认 Observer 真的注册成功了。addObserver是幂等的同一个 Observer 注册两次只会生效一次。如果你用的是匿名内部类每次new出来的都是不同对象会导致重复注册。第二步确认 Owner 的状态在变化。如果 Owner 是自定义的检查有没有调用setCurrentState或handleLifecycleEvent。我见过有人在自定义 View 里实现了 LifecycleOwner但忘了在onAttachedToWindow里推进状态结果 Observer 永远停在 INITIALIZED。第三步检查事件和状态的对应关系。ON_CREATE 对应 CREATEDON_START 对应 STARTEDON_RESUME 对应 RESUMED。如果你在onStart里注册 Observer它会先收到 ON_CREATE 再收到 ON_START这是正常的追平机制。5.2 内存泄漏的排查Lifecycle 本身设计上是防泄漏的——LifecycleRegistry 持有 Owner 的弱引用Observer 注册在 Registry 上。但如果你在 Observer 里持有了 Activity 的强引用或者 Observer 本身是个非静态内部类泄漏照样会发生。排查方法用 LeakCanary 跑一遍看引用链里有没有LifecycleRegistry相关的节点。如果有说明 Observer 没被正确移除。正常情况下Activity 销毁时 LifecycleRegistry 会分发 ON_DESTROY然后自动清理所有 Observer。但如果你的 Observer 在 ON_DESTROY 里做了耗时操作或者抛了异常清理可能不完整。注意LifecycleRegistry在 Owner 进入 DESTROYED 状态后会拒绝新的 Observer 注册并且会清空mObserverMap。所以如果你在 onDestroy 之后还试图注册 Observer是无效的。5.3 状态判断的常见误区很多人喜欢在 Observer 里写这样的代码Override public void onStateChanged(LifecycleOwner owner, Lifecycle.Event event) { if (owner.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) { // 做某事 } }这段代码在大多数情况下没问题但在事件分发过程中getCurrentState()返回的是 Owner 的当前状态而不是 Observer 的状态。如果 Owner 正在从 RESUMED 回退到 CREATEDgetCurrentState()可能已经是 CREATED但你的 Observer 还没收到 ON_PAUSE 事件。这种时序差异在复杂场景下会导致 bug。更安全的做法是直接根据 event 类型判断而不是查 Owner 的状态Override public void onStateChanged(LifecycleOwner owner, Lifecycle.Event event) { switch (event) { case ON_START: // 明确知道是 onStart break; case ON_STOP: // 明确知道是 onStop break; } }5.4 常见问题速查表问题现象可能原因排查方向Observer 完全不触发未注册或 Owner 状态未推进检查 addObserver 和 setCurrentState只触发部分事件注册时机晚于状态推进确认追平机制是否生效事件顺序错乱在分发过程中修改了 Observer 列表避免在 onStateChanged 里增删 Observer内存泄漏Observer 持有外部强引用用 LeakCanary 查引用链状态判断不准混用 Owner 状态和 Observer 状态优先根据 event 类型判断注解方式不生效注解处理器未启用检查 annotationProcessor 配置6. 几个容易被忽略的进阶细节6.1 ProcessLifecycleOwner 的应用ProcessLifecycleOwner是整个应用进程级别的 LifecycleOwner它把整个 App 的前后台切换抽象成了生命周期事件。ON_START 对应 App 进入前台ON_STOP 对应 App 进入后台。这个组件在做应用切后台时暂停某些任务的场景下非常有用比如暂停轮询、保存草稿、断开长连接等。它的实现原理是基于 Activity 的onStart和onStop计数当第一个 Activity 启动时延迟 700ms 分发 ON_START避免配置变更导致的误判当最后一个 Activity 停止时延迟 700ms 分发 ON_STOP。这个延迟是为了处理 Activity 之间的跳转避免在页面切换时误触发前后台事件。6.2 Lifecycle 与协程的深度结合lifecycleScope和viewModelScope是 Lifecycle 在协程时代最重要的两个扩展。lifecycleScope绑定的是 Activity/Fragment 的生命周期viewModelScope绑定的是 ViewModel 的生命周期。两者的区别在于Activity 旋转屏幕重建时lifecycleScope会被取消但viewModelScope不会因为 ViewModel 存活于配置变更之上。repeatOnLifecycle的源码实现值得一看它内部用的是suspendCancellableCoroutine加上 LifecycleEventObserver在 ON_START 时 resume 协程在 ON_STOP 时 cancel 协程。这种设计让协程的取消和生命周期严格对齐不会出现页面已经不可见但协程还在跑的情况。6.3 自定义 LifecycleObserver 的线程安全LifecycleRegistry 的事件分发是在主线程进行的因为 Activity 的生命周期回调本身就在主线程。但如果你在 Observer 里启动了子线程并且在子线程里访问了 Observer 的状态就需要自己做同步。我见过一个案例Observer 在 onStart 里启动了一个线程去加载数据加载完成后直接更新 UI结果 Activity 已经 onStop 了导致崩溃。正确的做法是在更新 UI 前检查lifecycle.currentState.isAtLeast(STARTED)或者用lifecycleScope.launch让协程自动处理。6.4 源码阅读的推荐路径如果你想自己啃一遍 Lifecycle 的源码我建议按这个顺序先看Lifecycle.java理解 State 和 Event 的枚举定义以及getTargetState()的映射关系再看LifecycleRegistry.java重点看addObserver、handleLifecycleEvent、sync、forwardPass、backwardPass这五个方法然后看Lifecycling.java理解 Observer 的适配逻辑最后看ReportFragment.java理解 Activity 是如何把生命周期回调转发给 LifecycleRegistry 的ReportFragment是个很巧妙的设计。AndroidX 没有直接修改 Activity 的基类而是通过一个无 UI 的 Fragment 注入到 Activity 里利用 Fragment 的生命周期回调来驱动 LifecycleRegistry。这样既不需要开发者改继承关系又能保证所有 Activity 都能用上 Lifecycle。7. 我在实际项目里踩过的坑说几个真实踩过的坑都是文档里不会写的。第一个坑在 Observer 的 onDestroy 里做异步操作。有一次我在 onDestroy 里发了一个网络请求去上报日志结果 Activity 已经销毁回调回来的时候 View 已经没了直接 NPE。后来改成用ProcessLifecycleOwner在应用切后台时上报问题解决。第二个坑多个 Observer 的执行顺序不确定。FastSafeIterableMap的遍历顺序是插入顺序但如果你在分发过程中动态增删 Observer顺序会变得不可预测。我遇到过一个 bug两个 Observer 都监听 ON_STARTA 依赖 B 先执行结果因为注册顺序反了导致 A 拿不到 B 初始化好的数据。解决办法是不要依赖 Observer 之间的执行顺序每个 Observer 都应该自包含。第三个坑在自定义 View 里实现 LifecycleOwner 时忘记处理配置变更。View 的onAttachedToWindow和onDetachedFromWindow在屏幕旋转时会各触发一次如果直接在这两个方法里推进状态会导致 Observer 收到一次完整的 ON_START/ON_STOP 循环。正确的做法是结合ViewTreeLifecycleOwner或者用isInEditMode判断避免在配置变更时误触发。第四个坑注解方式的 Observer 在混淆后失效。OnLifecycleEvent依赖反射查找方法如果开启了混淆方法名被改了反射就找不到。虽然 AndroidX 提供了 keep 规则但如果你自己写了自定义的注解处理器一定要记得加混淆配置。这也是我后来全面转向DefaultLifecycleObserver的原因之一。8. 后续可以怎么扩展Lifecycle 本身的内容到这里基本讲完了但它衍生出来的东西还有很多可以挖。比如SavedStateHandle是怎么和 Lifecycle 配合做状态恢复的LifecycleService是怎么把 Service 的生命周期也纳入进来的LifecycleCameraController是怎么用 Lifecycle 管理相机资源的。这些组件都是建立在 Lifecycle 这套状态机之上的理解了底层上层的东西看一遍就懂了。如果你正在做组件化或者基础库开发我强烈建议把 Lifecycle 的源码完整读一遍。它的代码量不大但设计密度很高尤其是sync()方法里那种循环直到所有 Observer 对齐的思路在很多需要状态同步的场景下都可以借鉴。我自己后来做的一个状态管理库核心的同步逻辑就是照着 LifecycleRegistry 抄的稳定跑了两年没出过问题。