Jetpack Lifecycle 状态机详解

3 阅读5分钟

Jetpack Lifecycle 状态机详解

在上一篇文章中,对Lifecycle做了一下了解,但发现其中一个重要的知识点没有提到,就是它的状态如何转换的,里面涉及到一个状态机的概念,今天就一起来看看状态机,和状态机在Lifecycle中的使用。

状态机基础概念

状态机定义

状态机是一种数学模型,用于描述对象在其生命周期中可能经历的各种状态,以及触发状态转换的事件和条件。它包含:

  • 状态(State):对象在生命周期中的稳定阶段
  • 事件(Event):触发状态转换的动作
  • 转换(Transition):从一个状态到另一个状态的变化过程

状态机原理

  1. 有限状态:对象只能处于预定义的有限状态之一
  2. 事件驱动:状态转换由特定事件触发
  3. 确定性:给定当前状态和事件,下一个状态是确定的
  4. 单向流动:状态转换通常遵循特定方向(如生命周期前进或回退)

Lifecycle 状态机详解

在 Jetpack Lifecycle 中,状态机精确描述了 Android 组件(Activity/Fragment)的生命周期变化:

状态(State)定义

状态常量值描述
INITIALIZED0初始状态(对象已创建但未进入生命周期)
CREATED1onCreate() 之后,onStart() 之前
STARTED2onStart() 之后,onResume() 之前
RESUMED3onResume() 之后(完全可见在前台)
DESTROYED4onDestroy() 之后(生命周期结束)

事件(Event)定义

事件常量值对应回调
ON_CREATE0onCreate()
ON_START1onStart()
ON_RESUME2onResume()
ON_PAUSE3onPause()
ON_STOP4onStop()
ON_DESTROY5onDestroy()
ON_ANY6任意事件

状态转换规则

Lifecycle 使用严格的状态转换机制,确保状态转换符合 Android 生命周期逻辑:

stateDiagram-v2
    [*] --> INITIALIZED
    INITIALIZED --> CREATED: ON_CREATE
    CREATED --> STARTED: ON_START
    STARTED --> RESUMED: ON_RESUME
    RESUMED --> STARTED: ON_PAUSE
    STARTED --> CREATED: ON_STOP
    CREATED --> DESTROYED: ON_DESTROY
    DESTROYED --> [*]
    
    note right of INITIALIZED
        初始状态:组件已实例化但
        未进入生命周期回调
    end note
    
    note left of CREATED
        CREATED状态:
        onCreate()已执行
        但组件不可见
    end note
    
    note right of STARTED
        STARTED状态:
        onStart()已执行
        组件可见但未在前台
    end note
    
    note left of RESUMED
        RESUMED状态:
        onResume()已执行
        组件完全可见在前台
    end note

详细转换流程

1. 前进流程(启动/恢复)
INITIALIZED 
  → [ON_CREATE] → CREATED 
  → [ON_START] → STARTED 
  → [ON_RESUME] → RESUMED

示例场景:Activity 启动

// 状态变化流程:
// 1. Activity 实例化:INITIALIZED
// 2. onCreate() 执行:分发 ON_CREATE 事件 → CREATED
// 3. onStart() 执行:分发 ON_START 事件 → STARTED
// 4. onResume() 执行:分发 ON_RESUME 事件 → RESUMED
2. 后退流程(暂停/停止)
RESUMED 
  → [ON_PAUSE] → STARTED 
  → [ON_STOP] → CREATED 
  → [ON_DESTROY] → DESTROYED

示例场景:用户按下返回键

// 状态变化流程:
// 1. onPause() 执行:分发 ON_PAUSE 事件 → STARTED
// 2. onStop() 执行:分发 ON_STOP 事件 → CREATED
// 3. onDestroy() 执行:分发 ON_DESTROY 事件 → DESTROYED
3. 部分回退流程(如切换到其他应用)
RESUMED → [ON_PAUSE] → STARTED → [ON_STOP] → CREATED

示例场景:用户按 Home 键

// 状态变化流程:
// 1. onPause() 执行:ON_PAUSE → STARTED
// 2. onStop() 执行:ON_STOP → CREATED
// 当用户返回时:
// 3. onRestart() 执行(无对应事件)
// 4. onStart() 执行:ON_START → STARTED
// 5. onResume() 执行:ON_RESUME → RESUMED

状态转换规则说明

  1. 不可跳跃状态

    • 不能从 CREATED 直接到 RESUMED,必须经过 STARTED
    • 不能从 RESUMED 直接到 CREATED,必须经过 STARTED
  2. 事件与状态对应关系

    • ON_CREATE 事件后状态总是变为 CREATED
    • ON_START 事件后状态总是变为 STARTED
    • ON_RESUME 事件后状态总是变为 RESUMED
    • ON_PAUSE 事件后状态总是变为 STARTED
    • ON_STOP 事件后状态总是变为 CREATED
    • ON_DESTROY 事件后状态总是变为 DESTROYED
  3. 特殊转换情况

    • 配置变更时:先执行完整销毁流程到 DESTROYED,然后重新初始化
    • 从后台返回:从 CREATEDSTARTEDRESUMED,不经过 INITIALIZED

状态机实现原理

LifecycleRegistry 中的核心处理逻辑:

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    State next = getStateAfter(event);
    moveToState(next);
}

static State getStateAfter(Event event) {
    switch (event) {
        case ON_CREATE:
        case ON_STOP:
            return State.CREATED;
        case ON_START:
        case ON_PAUSE:
            return State.STARTED;
        case ON_RESUME:
            return State.RESUMED;
        case ON_DESTROY:
            return State.DESTROYED;
        case ON_ANY:
            // 不会改变状态
    }
    throw new IllegalArgumentException("Unexpected event value " + event);
}

private void moveToState(State next) {
    if (mState == next) return;
    
    mState = next;
    
    if (mHandlingEvent || mAddingObserverCounter != 0) {
        // 延迟处理
        mNewEventOccurred = true;
        return;
    }
    
    mHandlingEvent = true;
    sync(); // 同步状态给所有观察者
    mHandlingEvent = false;
}

状态机使用注意事项

  1. 状态同步

    • 当添加新观察者时,会立即收到从当前状态回溯到初始状态的所有事件
    • 例如:当前状态为 RESUMED 时添加观察者,会依次收到: ON_CREATE → ON_START → ON_RESUME
  2. 状态查询

    // 获取当前状态
    val currentState = lifecycle.currentState
    
    // 检查是否至少处于某个状态
    if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
        // 安全执行需要 STARTED 状态的操作
    }
    
  3. 边界情况处理

    • ON_DESTROY 事件可能不会在配置变更时触发
    • 避免在 ON_DESTROY 中执行关键资源释放,优先使用 ON_STOP
  4. 状态与事件关系

    graph LR
    A[事件] --> B[状态变化]
    ON_CREATE --> CREATED
    ON_START --> STARTED
    ON_RESUME --> RESUMED
    ON_PAUSE --> STARTED
    ON_STOP --> CREATED
    ON_DESTROY --> DESTROYED
    

实际应用场景

场景:视频播放器状态管理

class VideoPlayerObserver(private val context: Context) : DefaultLifecycleObserver {

    override fun onStart(owner: LifecycleOwner) {
        // 状态:STARTED
        // 初始化播放器但不自动播放
        initPlayer()
    }

    override fun onResume(owner: LifecycleOwner) {
        // 状态:RESUMED
        // 开始播放
        startPlayback()
    }

    override fun onPause(owner: LifecycleOwner) {
        // 状态:STARTED
        // 暂停播放(保持播放状态)
        pausePlayback()
    }

    override fun onStop(owner: LifecycleOwner) {
        // 状态:CREATED
        // 释放播放器资源
        releasePlayer()
    }
}

// 在Activity中使用
class VideoActivity : AppCompatActivity() {
    private lateinit var playerObserver: VideoPlayerObserver

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        playerObserver = VideoPlayerObserver(this)
        lifecycle.addObserver(playerObserver)
    }
}

状态转换跟踪

  1. Activity 启动:INITIALIZED → CREATED → STARTED → RESUMED

    • 依次触发:onCreate() → onStart() → onResume()
    • 播放器:初始化 → 开始播放
  2. 用户按下 Home 键:RESUMED → STARTED → CREATED

    • 依次触发:onPause() → onStop()
    • 播放器:暂停 → 释放资源
  3. 用户返回应用:CREATED → STARTED → RESUMED

    • 依次触发:onRestart() → onStart() → onResume()
    • 播放器:重新初始化 → 继续播放

总结

Jetpack Lifecycle 的状态机:

  1. 提供了标准化的生命周期状态管理
  2. 通过明确定义的状态和事件确保转换的可靠性
  3. 支持状态查询和状态条件检查
  4. 自动处理观察者的状态同步
  5. 简化了生命周期相关组件的开发

理解状态机的工作原理能帮助开发者:

  • 编写更可靠的与生命周期相关的代码
  • 避免常见的内存泄漏和状态不一致问题
  • 创建更易于维护的生命周期感知组件
  • 正确处理边界情况和异常状态转换

通过合理利用 Lifecycle 状态机,可以显著提升 Android 应用的稳定性和用户体验。