4 LifecycleRegistry 状态机详解

4.1 状态与事件枚举

LifecycleRegistry 依赖一个有限状态机(FSM)管理观察者通知。共有 5 个状态和 6 个事件,定义在 Lifecycle.State 与 Lifecycle.Event 中。

枚举名称说明
StateDESTROYEDOwner 已销毁,不应再发出任何事件
INITIALIZEDOwner 已创建但未调用 onCreate
CREATEDonCreate 之后、onStart 之前;或 onStop 之后
STARTEDonStart 之后、onResume 之前;或 onPause 之后
RESUMEDonResume 之后,处于前台
EventON_CREATE等价于 Activity.onCreate / Fragment.onCreate
ON_START等价于 onStart
ON_RESUME等价于 onResume
ON_PAUSE等价于 onPause
ON_STOP等价于 onStop
ON_DESTROY等价于 onDestroy

状态转换规则:向下前进需依次经过所有中间状态,向上回退则直接跳到目标状态(downgrade 会折叠中间状态)。

LifecycleRegistry 状态转换图 LifecycleRegistry 状态转换示意 INITIALIZED CREATED STARTED RESUMED DESTROYED ON_CREATE ON_START ON_RESUME ON_PAUSE ON_STOP ON_DESTROY 💡 回退时直接跳到目标 状态,中间状态被折叠。 前进必须逐级经过。
关键点:状态机保证了“同一状态不会重复发送”和“降级时中间观察者仍可收到事件”。

4.2 手工派发事件流程

通过 LifecycleRegistry.handleLifecycleEvent(Lifecycle.Event) 手工触发状态转换。内部流程:

  1. 校验当前状态与事件是否合法(如从 RESUMED 不能直接发 ON_CREATE)。
  2. 根据事件计算目标状态(getStateAfter(event))。
  3. 调用 moveToState(state),沿备份的状态链向上或向下遍历。
  4. 对每个中间状态通知所有观察者(Observer 的 onStateChanged 回调)。
  5. 最终设置 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
常见错误:
  1. 忘记调用 setCurrentState(DESTROYED),导致观察者无法收到 ON_DESTROY 事件。
  2. 直接在 getLifecycle() 返回一个新创建的 LifecycleRegistry(导致状态丢失)。
  3. 在子线程调用 handleLifecycleEvent(必须在主线程)。
最佳实践:对于 Android 组件,直接继承 ComponentActivity 或 Fragment 即可自动获得正确的 LifecycleOwner。仅在构建纯 Java 状态机或测试 Mock 时才需要手写。