Jetpack Lifecycle 状态机详解

Jetpack Lifecycle 状态机详解

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

状态机基础概念

状态机定义

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

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

状态机原理

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

Lifecycle 状态机详解

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

状态(State)定义

状态 常量值 描述
INITIALIZED 0 初始状态(对象已创建但未进入生命周期)
CREATED 1 onCreate() 之后,onStart() 之前
STARTED 2 onStart() 之后,onResume() 之前
RESUMED 3 onResume() 之后(完全可见在前台)
DESTROYED 4 onDestroy() 之后(生命周期结束)

事件(Event)定义

事件 常量值 对应回调
ON_CREATE 0 onCreate()
ON_START 1 onStart()
ON_RESUME 2 onResume()
ON_PAUSE 3 onPause()
ON_STOP 4 onStop()
ON_DESTROY 5 onDestroy()
ON_ANY 6 任意事件

状态转换规则

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. 前进流程(启动/恢复)
css 复制代码
INITIALIZED 
  → [ON_CREATE] → CREATED 
  → [ON_START] → STARTED 
  → [ON_RESUME] → RESUMED

示例场景:Activity 启动

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

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

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

示例场景:用户按 Home 键

java 复制代码
// 状态变化流程:
// 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 中的核心处理逻辑:

java 复制代码
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. 状态查询

    kotlin 复制代码
    // 获取当前状态
    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

实际应用场景

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

kotlin 复制代码
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 应用的稳定性和用户体验。

相关推荐
蛋卷卷-1 小时前
【UE5】如何开发安卓项目的udp客户端
android·ue5·udp
Lud_2 小时前
OpenGL ES 设置光效效果
android·opengl es
solo_993 小时前
使用python实现 大批量的自动搜索安装apk
android
移动开发者1号6 小时前
Android多进程数据共享:SharedPreferences替代方案详解
android·kotlin
移动开发者1号6 小时前
网络请求全链路监控方案设计
android·kotlin
移动开发者1号6 小时前
Android存储选择指南:应用专属目录 vs 媒体库目录
android·kotlin
generallizhong8 小时前
android 省市区联动选择
android·java·算法
法迪14 小时前
Android中Native向System Service进行Binder通信的示例
android·binder
darling_user17 小时前
Android14 耳机按键拍照
android