第4章 Activity生命周期状态机实现:状态定义、转换条件、超时机制

Activity生命周期状态机是ActivityManagerService(AMS)调度Activity的核心模型。本章定义一套完整的私有状态枚举、合法转换条件以及超时保护机制,供后续定制AMS时直接使用。

4.1 状态定义

AMS内部使用一组离散状态描述Activity的运行时阶段,不同于对外暴露的onCreate/onStart等回调。本章状态枚举从AOSP源码ActivityRecord中提炼,定制场景下可扩展或裁剪。

状态名枚举值说明所属进程阶段
INITIALIZING0x01ActivityRecord创建后尚未启动应用未创建
STARTED0x02已发出启动请求,等待应用进程响应应用进程就绪
RESUMED0x03Activity可见且获得焦点前台
PAUSING0x04正在执行暂停操作(回调onPause)退出前台
PAUSED0x05暂停完成,Activity不可见后台可见?不可见
STOPPING0x06正在执行停止操作(回调onStop)不可见
STOPPED0x07停止完成,保留状态但不可见后台
DESTROYING0x08正在执行销毁操作(回调onDestroy)销毁中
DESTROYED0x09销毁完成,等待从Record列表移除已结束
定制注意: 若需要多窗口或分屏状态,可新增MULTI_WINDOW_PAUSED、PICTURE_IN_PICTURE等状态,但需同步修改转换条件与超时处理。

4.2 状态转换条件

合法转换定义在一张有向状态转换表中。以下为定制AMS中必须遵守的核心规则,不可任意跨状态跳转。

当前状态触发事件下一状态条件/备注
INITIALIZINGattachApplication()STARTED应用进程已绑定
STARTEDactivityResumed()RESUMED应用调用onResume完成
RESUMEDschedulePauseActivity()PAUSING新Activity启动或返回Home
PAUSINGactivityPaused()PAUSED应用onPause回调返回
PAUSEDscheduleStopActivity()STOPPINGActivity不再可见
STOPPINGactivityStopped()STOPPED应用onStop回调返回
STOPPEDscheduleDestroyActivity()DESTROYING需要释放资源
DESTROYINGactivityDestroyed()DESTROYED应用onDestroy回调返回
任意中途状态processDied()DESTROYED进程死亡强制结束
禁止非法转换: 例如,直接从INITIALIZING跳转到RESUMED,或从PAUSED跳转到RESUMED而不经过STARTED,会导致回调顺序错乱和ANR。所有转换必须经AMS维护的mState字段校验。

4.3 超时机制

为避免应用进程阻塞AMS主线程,每个涉及长耗时回调(onPause、onStop、onDestroy)的状态都配置独立超时值。超时后AMS强制推进状态并发送错误报告。

等待回调超时时间(ms)超时处理策略
activityPaused()500强制设为PAUSED,输出ANR警告
activityStopped()10000强制设为STOPPED,杀死进程
activityDestroyed()10000强制设为DESTROYED,清理Record

超时计时器实现示例:

// 在AMS主线程Handler中调度
private void scheduleActivityTimeout(ActivityRecord r, int timeoutMs) {
    Message msg = mHandler.obtainMessage(HANDLE_ACTIVITY_TIMEOUT, r);
    mHandler.sendMessageDelayed(msg, timeoutMs);
}

// 收到超时消息后执行强制转换
private void handleActivityTimeout(ActivityRecord r) {
    synchronized (mLock) {
        if (r.state == ActivityState.PAUSING) {
            r.state = ActivityState.PAUSED;
            dispatchActivityPausedLocked(r);
            Slog.w(TAG, "Force PAUSED due to timeout for " + r);
        }
        // 类似处理STOPPING、DESTROYING
    }
}
定制调优: 针对低端设备或特定场景(如VR、车机),可以动态调整超时值。建议通过SystemProperties暴露三个配置项:persist.activity.timeout.pause、persist.activity.timeout.stop、persist.activity.timeout.destroy。

4.4 状态机整体结构

Activity生命周期状态机(定制AMS) INITIALIZING STARTED RESUMED PAUSING PAUSED STOPPING STOPPED DESTROYING DESTROYED ⏱ 超时强制推进 PAUSING/STOPPING/DESTROYING ❌ 非法转换需拦截 直接JUMP至RESUMED等 定制时建议保留

4.5 调试与验证

状态机实现完成后,建议通过以下方法验证正确性:

  • 日志标记:在每个状态转换点输出Slog.i(TAG, "Statemachine: " + oldState + " -> " + newState),配合logcat -s ActivityManager:I观察。
  • 单元测试:使用Robolectric模拟AMS主线程,注入虚假ClientTransaction验证转换路径。
  • 压力测试:启动大量Activity并快速旋转屏幕,检查是否出现状态滞留或双重回调。
// 验证超时触发日志示例片段
adb logcat -s ActivityManager:I | grep "Timeout\|Force\|state="

// 若看到以下日志说明超时机制生效
ActivityManager: Force PAUSED due to timeout for ActivityRecord{xxx}
ActivityManager: state=PAUSING -> PAUSED (timeout)
常见错误: 超时消息未在activityPaused()等回调到达时及时移除,导致状态被双重强制转换。务必在回调处理中加入mHandler.removeMessages(HANDLE_ACTIVITY_TIMEOUT, r)清理待执行超时消息。

4.6 性能与稳定性优化

  • 超时容忍度动态调整:根据设备CPU负载或帧率下降,临时缩短PAUSING超时(如从500ms降到300ms),防止卡顿堆叠。
  • 批量状态变更:若同时处理多个Activity,可合并scheduleActivityTimeout调用,减少Handler消息队列压力。
  • 安全锁粒度:状态机操作在mLock同步块内执行,但超时Handler回调中加锁需谨慎,避免死锁。建议在Handler消息处理中使用synchronized (mLock)时只做最短临界区。

本章定义的状态枚举、转换表、超时配置可直接嵌入AMS源码的ActivityRecord.java和ActivityStack.java中。下一阶段将结合第5章“Activity启动流程同步回调定制”,把状态机与客户端事务调度整合。