何谓生命周期?
生命周期是系统中普遍存在的隐性时序契约,例如「若执行 A,未来某刻必须执行 B」的步骤顺序限制。常见的是 Activity 的 onCreate
/onDestroy
,它们是 Activity 的生命周期;Fragment 和 Navigation 也有各自的生命周期。
时序分解
《软件设计的哲学》 5.3 Temporal decomposition 时间分解 与 生命周期 讲述的是同一概念(本文将「时序分解」视为复杂度分类的一种 )。所谓时序分解,是指「无法被编译器/形式化验证的步骤顺序限制」。它会泄露非功能性的额外知识 ,造成认知负担与未知的未知。
而生命周期,就是一种时序分解。
架构原则:契约的形式化与委托
当系统足够复杂时,这种约束难以完全避免,这是开发与设计中无法规避的本质复杂度 。因此 Jetpack Lifecycle 的目标,就是把隐性契约形式化 并交由订阅者 履行。
解决方案的核心,是提供一个将「隐性契约」转化为「显性契约」的抽象框架:
- 原则一(形式化) :把人脑记忆的时序规则外显为
Lifecycle
(状态+事件),让契约可被观察与执行。 - 原则二(外显与订阅) :
Lifecycle
公开状态与事件;LifecycleObserver
主动订阅并在其内部封装履约知识(启停时机、绑/解资源、幂等/重入保障)。
架构模型:观察者模式的具体化
Lifecycle
的概念非常简单,它只是一个「可被观察的生命周期」对象:注册观察者来监听状态变化,也可以直接访问当前状态。
这就是要做的全部:观察生命周期状态变化。它最初就以响应式为目标设计,完全可以按照观察者模型来理解。
概念:观察者模式
- 原则 :
Lifecycle
的核心交互机制是观察者设计模式。 - 主体(Subject) :
Lifecycle
对象,持有权威状态,并负责通知。 - 观察者(Observer) :
LifecycleObserver
,被动接收状态更新并执行逻辑。
概念非常干净简单:你可以是生命周期主体让外部观察,也可以是观察者监听状态变化,就只是这样。
架构角色:模式的 API 映射(Architectural Roles: API Mapping of the Pattern)
Lifecycle
(形式化的契约 / 主体)
职责:定义时序契约的具体规则,并发布状态与事件。
LifecycleOwner
(主体的持有者)
职责:标识一个对象拥有一个可被观察的时序上下文。
LifecycleObserver
(观察者 / 知识的封装体)
职责:完整封装响应时序契约所需的全部知识与逻辑。
核心沟通模型:状态与事件(Core Communication Model: State and Event)
Event
(生命周期事件)
定义 :代表一个瞬间发生、触发状态迁移的动作 。
范式:事件驱动(Event-Driven),适用于处理离散、一次性的操作。
State
(生命周期状态)
定义 :代表一个持续性的、稳定的状况 。
范式:状态驱动(State-Driven),适用于管理在某个时间段内需要持续进行的任务。
事件 vs 状态
事件驱动(Event-Driven)
- 核心关注点:在某个时间点发生了什么事。
- 设计目的:为响应离散、一次性的触发提供明确的行为回调。
状态驱动(State-Driven)
- 核心关注点:在某个时间段内处于什么状况。
- 设计目的:为需要在某个条件下持续执行的任务,提供声明式、自动管理启停与取消的抽象。
Jetpack Lifecycle 中的状态驱动
状态只是事件驱动的概念映射 ,用若干事件界定出一段「成立中的区间」。例如
STARTED
状态,就是从ON_START
到ON_STOP
之间的持续时间。
实现的样板
因为依旧依赖事件驱动,直接实现会落回事件触发的启停:仍是「进入→开始、离开→结束」的成对样板。
协程的结构化并发
结构化并发的核心原则,是以层级结构治理协程的生命周期。在此结构中,「作用域」与「工作」都拥有各自的生命周期,并存在父子关系:
- 协程作用域(
CoroutineScope
) :作为父层,其自身的生命周期(从建立到取消)定义了一个最长的执行区间。 - 协程/工作(
Coroutine
/Job
) :所有在该作用域内启动的协程(其本质为一个「工作」Job
),作为子层,其生命周期被严格约束在父作用域的区间之内。父作用域的取消会向下传播,可靠地终止其所有子工作。这就是「以作用域承载区间、以取消实现收束」的机制。
协程 ⬌ 区间 ⬌ 生命周期
此三者的核心关系,是概念、结构与实现 的等价:生命周期状态是一个概念性区间 ,而协程的结构化并发 为此区间提供了实现性结构。更具体地说:
Lifecycle
定义了一个由事件界定的抽象区间。- 协程的
CoroutineScope
定义了一个由建立与取消界定的具体执行区间 ,其自身的生命周期由其在父层的「工作(Job
)」所代表。 - 运行在
scope
内的「协程」则是此区间中的具体任务。
因此,「生命周期状态」这个抽象概念,得以通过「协程作用域」这个具体结构来实现。这使得原本需要手动配对的生命周期操作,能够被一个由 scope
自动管理生命周期的协程任务所取代。
以协程实现的生命周期状态驱动
以协程实现状态驱动的本质,是将「生命周期状态」这一概念性区间,通过「协程作用域」这一实现性区间进行等价实现。其核心在于利用结构化并发的取消保证,把原本需要手动配对的「开始/结束」操作,统一在一个结构化的区块中。
官方提供的 API:对照表(事件 vs 状态)
事件驱动:处理「点」
DefaultLifecycleObserver
:语义化事件回调(onStart/onStop/...
),封装小型切点。LifecycleEventObserver
:监听所有事件,用匹配或枚举处理,适合桥接遗留回调或需精确拦截。
Compose 中的事件驱动
LifecycleEventEffect(event) { ... }
:在指定生命周期事件发生时执行一次性 side‑effect(组合作用域内)。
状态驱动:治理「区间」
repeatOnLifecycle(minState)
:在状态区间内自动启停协程区块。flowWithLifecycle(lifecycle, minState)
:以最小状态闸限进行数据流的收集。
Compose 中的状态驱动
collectAsStateWithLifecycle()
:Flow → State,自动对齐最小状态。LifecycleStartEffect
/LifecycleResumeEffect
:在 STARTED/RESUMED 区间内启动/撤回 side‑effect。
(默认 minActiveState = STARTED)
总结
何谓生命周期?
是开发中无法避免的「隐性时序契约」,它要求开发者手动维护有顺序限制的操作,是一种设计上的「时序分解」复杂性。
Jetpack Lifecycle 是什么?
Jetpack Lifecycle 是解决此问题的基础框架。它以观察者模式,把隐性规则外显并可订阅,让你不再手动管理这些细节,而是交给框架保证执行。
该怎么建模,怎么用?
在实践中,应遵循以下原则:
- 辨别模型:一次性、离散响应 → 用「事件」;持续性任务(尤其数据流) → 用「状态」。
- 优先状态驱动 :优先选择基于结构化并发的状态驱动 API,例如
repeatOnLifecycle
,从根本上避免「成对样板」错误。
Bonus:为何 Lifecycle
是 class,而 LifecycleOwner
是 interface
这是一个有趣的设计议题,建议在下一章(设计理念与源码分析)一并讨论。