4. LifecycleRegistry状态机详解
4.1 状态与事件枚举
LifecycleRegistry 依赖一个有限状态机(FSM)管理观察者通知。共有 5 个状态和 6 个事件,定义在 Lifecycle.State 与 Lifecycle.Event 中。
| 枚举 | 名称 | 说明 |
|---|---|---|
| State | DESTROYED | Owner 已销毁,不应再发出任何事件 |
| INITIALIZED | Owner 已创建但未调用 onCreate | |
| CREATED | onCreate 之后、onStart 之前;或 onStop 之后 | |
| STARTED | onStart 之后、onResume 之前;或 onPause 之后 | |
| RESUMED | onResume 之后,处于前台 | |
| Event | ON_CREATE | 等价于 Activity.onCreate / Fragment.onCreate |
| ON_START | 等价于 onStart | |
| ON_RESUME | 等价于 onResume | |
| ON_PAUSE | 等价于 onPause | |
| ON_STOP | 等价于 onStop | |
| ON_DESTROY | 等价于 onDestroy |
状态转换规则:向下前进需依次经过所有中间状态,向上回退则直接跳到目标状态(downgrade 会折叠中间状态)。
关键点:状态机保证了“同一状态不会重复发送”和“降级时中间观察者仍可收到事件”。
4.2 手工派发事件流程
通过 LifecycleRegistry.handleLifecycleEvent(Lifecycle.Event) 手工触发状态转换。内部流程:
- 校验当前状态与事件是否合法(如从 RESUMED 不能直接发 ON_CREATE)。
- 根据事件计算目标状态(
getStateAfter(event))。 - 调用
moveToState(state),沿备份的状态链向上或向下遍历。 - 对每个中间状态通知所有观察者(Observer 的 onStateChanged 回调)。
- 最终设置
mState = targetState。
// 典型手工派发示例(自定义 LifecycleOwner 内)
public class MyLifecycleOwner implements LifecycleOwner {
private final LifecycleRegistry registry = new LifecycleRegistry(this);
@NonNull @Override
public Lifecycle getLifecycle() { return registry; }
public void onMyCreate() {
registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}
public void onMyStart() {
registry.handleLifecycleEvent(Lifecycle.Event.ON_START);
}
// ……
}
注意:事件必须按顺序调用,不可跳过。例如先发 ON_START 再发 ON_CREATE 会导致 IllegalStateException。
4.3 markState 与 setCurrentState 区别
markState 和 setCurrentState 都是 LifecycleRegistry 的方法,但语义完全不同。
| 方法 | 可见性 | 功能 | 是否触发事件 | 源码路径 |
|---|---|---|---|---|
setCurrentState(State) |
public | 直接设置新状态,执行完整的状态转换逻辑(包括通知观察者) | 是 | LifecycleRegistry.java:100+ |
markState(State) |
包内可见(default) | 仅标记内部 mState,不执行任何转换,也不通知观察者 |
否 | LifecycleRegistry.java:80+ |
// setCurrentState 会出发完整流程
registry.setCurrentState(State.CREATED);
// markState 只是赋值,不会通知观察者(常用于初始化阶段)
// markState 是 Package-private,外部通常无法调用
registry.markState(State.INITIALIZED); // 仅合法在 LifecycleRegistry 内部或测试中
什么时候用 markState?在 LifecycleRegistry 构造时(
mState = INITIALIZED)以及某些内部缓存场景。外部自定义 LifecycleOwner 永远使用 setCurrentState 或 handleLifecycleEvent。
4.4 自定义 LifecycleOwner 正确写法
正确的自定义 LifecycleOwner 应满足:
- 持有
LifecycleRegistry实例并实现getLifecycle()。 - 在生命周期关键节点调用
handleLifecycleEvent或setCurrentState。 - 支持
DefaultLifecycleObserver或注解方式注册观察者。
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
import androidx.annotation.NonNull;
public class TimerOwner implements LifecycleOwner {
private final LifecycleRegistry registry = new LifecycleRegistry(this);
@NonNull @Override
public Lifecycle getLifecycle() {
return registry;
}
public void startTimer() {
registry.setCurrentState(Lifecycle.State.STARTED);
}
public void stopTimer() {
registry.setCurrentState(Lifecycle.State.CREATED);
}
public void destroy() {
registry.setCurrentState(Lifecycle.State.DESTROYED);
}
}
// 使用方式
TimerOwner owner = new TimerOwner();
owner.getLifecycle().addObserver(new DefaultLifecycleObserver() {
@Override
public void onStart(@NonNull LifecycleOwner lifecycleOwner) {
System.out.println("Timer started");
}
});
owner.startTimer(); // 触发 onStart
常见错误:
- 忘记调用
setCurrentState(DESTROYED),导致观察者无法收到ON_DESTROY事件。 - 直接在
getLifecycle()返回一个新创建的LifecycleRegistry(导致状态丢失)。 - 在子线程调用
handleLifecycleEvent(必须在主线程)。
最佳实践:对于 Android 组件,直接继承
ComponentActivity 或 Fragment 即可自动获得正确的 LifecycleOwner。仅在构建纯 Java 状态机或测试 Mock 时才需要手写。