lifecycle相关的几个核心机制:
1. 生命周期的“状态”与“事件” (State vs. Event)
很多开发者会混淆这两个概念,但在代码逻辑中,它们的区别至关重要:
-
Event(事件):是瞬时的动作(如
ON_START,ON_RESUME)。你可以在Observer中捕捉这些“点”。 -
State(状态):是持续的区间(如
STARTED,RESUMED)。 -
关键应用:当你执行一个异步任务(比如网络请求)回来时,不应该检查事件,而应该检查状态:
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED))。这能确保你在 UI 还没销毁、且至少对用户可见时才操作 UI。
2. LifecycleScope 与协程的深度集成
在 SmartPDF 这种涉及大量 IO 和文件读取的应用中,利用 Lifecycle 控制协程是性能和安全的关键:
-
lifecycleScope.launch:当 Activity 被销毁时,协程会自动取消。防止了后台任务在页面消失后继续运行。 -
repeatOnLifecycle(核心推荐):这是目前 Compose 和 View 体系中处理数据流最安全的方式。 -
思想:当 Activity 掉到后台(
onStop),它会自动挂起协程,停止收集数据,从而节省 CPU 和电量;当回到前台(onStart),它会自动重启。
3. ProcessLifecycleOwner (全局生命周期)
如果你需要知道“整个 App”是进入了后台还是回到了前台(例如:当 App 从后台切回时弹出一个开屏广告或检查锁定状态),你不需要在每个 Activity 里写逻辑。
-
用法:使用
ProcessLifecycleOwner.get().lifecycle.addObserver(...)。 - 思想:它将整个应用的进程抽象为一个单一的生命周期。
4. 生命周期在 Fragment 中的“两对”坑
这是很多 Senior 开发者也容易翻车的地方。Fragment 拥有两个生命周期:
-
Fragment 自身的生命周期 (
getLifecycle())。 -
Fragment 视图的生命周期 (
getViewLifecycleOwner().getLifecycle())。
-
避坑指南:在观察 UI 相关的数据流(如
ViewModel的 Flow)时,**永远使用viewLifecycleOwner**。否则,如果 Fragment 的视图被销毁但实例还在(比如进入了返回栈),旧的观察者不会被清理,会导致严重的内存泄漏和多次订阅。
5. Lifecycle.State.INITIALIZED 之后的内存安全
了解 Lifecycle 是如何清理 Observer 的。LifecycleRegistry 内部使用了自定义的 SafeIterableMap,它允许你在遍历观察者列表时动态添加或删除观察者而不会抛出 ConcurrentModificationException。
-
Senior 洞察:这意味着你可以在
onStop事件中安全地调用removeObserver(this)来实现“单次触发”的逻辑。
总结:你的知识体系地图
| 维度 | 进阶关键词 | 解决的问题 |
|---|---|---|
| 流控 | repeatOnLifecycle |
极致的电量和资源优化 |
| 安全 | isAtLeast(State) |
防止异步回调导致的 UI 崩溃 |
| 范围 | ProcessLifecycleOwner |
全局应用状态感知 |
| 避坑 | viewLifecycleOwner |
解决 Fragment 视图内存泄漏 |