☰
Android Lifecycle 源码深度解析:状态机设计与事件分发机制
2026/10/13 17:12:28 网站建设 项目流程

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、Registry

Lifecycle 的源码结构其实非常精简,核心就三个东西:

  • LifecycleOwner:生命周期持有者,任何想暴露生命周期的类都可以实现这个接口。Activity、Fragment 在 AndroidX 里都已经默认实现了它。
  • LifecycleObserver:生命周期观察者,一个空接口,具体的事件通过@OnLifecycleEvent注解或者DefaultLifecycleObserver接口来接收。
  • LifecycleRegistry:Lifecycle 的唯一实现类,负责管理所有 Observer 的注册、状态同步和事件分发。

这三者的关系可以用一句话概括:LifecycleOwner 持有一个 LifecycleRegistry,Observer 注册到 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 与 forwardPass

LifecycleRegistry 最核心的方法是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()) { Entry<LifecycleObserver, 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 都会被包装成ObserverWithState:

static 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。它支持三种形式:

  1. 直接实现LifecycleEventObserver接口的
  2. 实现DefaultLifecycleObserver接口的(通过FullLifecycleObserverAdapter适配)
  3. 使用@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. 实操落地:从零接入 Lifecycle

4.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 以上,建议直接用它,比注解方式更高效。

写一个最简单的 Observer:

public 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 里忘记调用setCurrentState,Observer 就永远收不到事件。

提示: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 对应 CREATED,ON_START 对应 STARTED,ON_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 回退到 CREATED,getCurrentState()可能已经是 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 的源码,我建议按这个顺序:

  1. 先看Lifecycle.java,理解 State 和 Event 的枚举定义,以及getTargetState()的映射关系
  2. 再看LifecycleRegistry.java,重点看addObserver、handleLifecycleEvent、sync、forwardPass、backwardPass这五个方法
  3. 然后看Lifecycling.java,理解 Observer 的适配逻辑
  4. 最后看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_START,A 依赖 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 抄的,稳定跑了两年没出过问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询