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 | 初始化完成,还没收到任何生命周期回调 |
| CREATED | onCreate 之后,或者 onStop 之后 |
| STARTED | onStart 之后,或者 onPause 之后 |
| RESUMED | onResume 之后,处于前台可见可交互 |
| DESTROYED | onDestroy 之后,生命周期终结 |
对应的事件有七个: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。它支持三种形式:
- 直接实现
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. 实操落地:从零接入 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 的源码,我建议按这个顺序:
- 先看
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_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 抄的,稳定跑了两年没出过问题。