Android14 AMS 剖析之Activity 启动分析之 pause 前台 Activity

120 阅读4分钟

通俗易懂讲解Activity启动时暂停前台Activity的机制

一、为什么需要暂停前台Activity?

想象你正在用手机刷抖音,突然想打开微信回消息。这时系统需要完成两个关键操作:

  1. 优雅退出当前界面:暂停抖音的播放,保存当前进度
  2. 准备新界面登场:加载微信聊天界面

暂停前台Activity就像舞台换幕时的场景切换:

  • 旧演员(前台Activity)需要暂时退场
  • 新演员(新Activity)在后台准备登场
  • 整个过程要保证观众(用户)看不到后台切换的混乱

二、暂停操作的触发时机

以下场景会触发暂停操作:

  1. 启动新Activity:点击App图标/跳转新页面
  2. 透明Activity覆盖:弹窗式界面(Dialog主题)出现
  3. 锁屏操作:系统级界面覆盖当前应用
  4. 横竖屏切换:配置变更导致的界面重建

三、系统如何执行暂停操作?(四步走战略)

1. 发起暂停指令(导演喊"卡")

  • 新Activity启动请求到达AMS(系统大管家)
  • AMS通过Binder通知前台Activity所在进程:"该暂停了"

2. 执行生命周期回调(演员谢幕流程)

java
	// 伪代码展示暂停流程

	public class ActivityThread {

	    void handlePauseActivity(IBinder token) {

	        // 1. 暂停界面绘制

	        ActivityClientRecord r = mActivities.get(token);

	        r.activity.performPause();

	        

	        // 2. 通知WMS(窗口管理服务)

	        mWindowManager.startFreezingScreen(r.activity, r.config);

	    }

	}

	 

	// Activity的暂停实现

	public class Activity {

	    final void performPause() {

	        callActivityOnPause(); // 触发onPause()回调

	        mActivityTransitionState.setEnterActivityOptions(this, null);

	        mWindow.closeAllPanels(); // 关闭所有面板

	    }

	}

3. 冻结界面渲染(舞台灯光渐暗)

  • WMS会执行以下操作:

    • 停止接收触摸事件
    • 冻结当前窗口Surface
    • 标记窗口状态为PAUSING

4. 返回执行结果(场记打板)

  • 前台Activity通过ApplicationThread回复AMS:"已暂停就绪"
  • AMS收到确认后,继续新Activity的启动流程

四、暂停期间的特殊处理

1. 进程优先级调整

  • 暂停的Activity所在进程会被降级:

    	前台进程 → 可见进程 → 服务进程 → 后台进程
    
  • 防止进程被系统误杀,但允许在内存紧张时优先回收

2. 状态保存机制

  • 自动保存非配置相关状态:

    java
    	// 系统自动保存/恢复的视图状态
    
    	onSaveInstanceState(Bundle outState) {
    
    	    outState.putInt("scroll_position", 100);
    
    	}
    
  • 开发者需手动保存配置相关状态(如当前登录态)

3. 异常处理机制

  • 设置暂停超时时间(默认10秒)

  • 超时未完成会触发ANR:

    	Activity pause timeout for ActivityRecord
    
  • 通过Trace文件定位卡顿原因

五、实际开发中的暂停优化技巧

1. 快速暂停策略

  • 在onPause()中释放重型资源:

    java
    	@Override
    
    	protected void onPause() {
    
    	    super.onPause();
    
    	    if (isFinishing()) {
    
    	        releaseCamera(); // 释放相机资源
    
    	        stopBackgroundThread(); // 停止后台线程
    
    	    }
    
    	}
    

2. 状态保存优化

  • 使用ViewModel保存业务数据:

    kotlin
    	class MyViewModel : ViewModel() {
    
    	    val data = MutableLiveData<String>()
    
    	}
    
  • 避免在onSaveInstanceState()中保存大数据

3. 界面冻结处理

  • 对复杂视图进行分层冻结:

    java
    	// 主线程执行
    
    	View rootView = getWindow().getDecorView().getRootView();
    
    	rootView.setDrawingCacheEnabled(true);
    
    	Bitmap cache = rootView.getDrawingCache();
    

六、暂停与恢复的完整生命周期

mermaid
	sequenceDiagram

	    participant User

	    participant AMS

	    participant OldActivity

	    participant NewActivity

	    

	    User->>AMS: 启动新Activity

	    AMS->>OldActivity: 发送暂停指令

	    OldActivity->>OldActivity: 执行onPause()

	    OldActivity-->>AMS: 暂停完成

	    AMS->>NewActivity: 启动新界面

	    NewActivity->>NewActivity: 执行onCreate/onResume

	    NewActivity-->>AMS: 就绪

	    AMS->>OldActivity: 发送停止指令(可选)

	    OldActivity->>OldActivity: 执行onStop()

七、设计哲学解析

  1. 渐进式冻结

    • 先暂停(PAUSED)再停止(STOPPED)
    • 类似电梯门关闭过程:先减速(暂停)再停止(完全关闭)
  2. 安全边界设计

    • 强制生命周期回调顺序:

      	onPause() → onStop() → onDestroy()
      
    • 防止出现"幽灵Activity"(已销毁但窗口残留)

  3. 性能平衡艺术

    • 暂停阶段完成80%的资源释放
    • 保留关键状态以便快速恢复
    • 类似汽车巡航控制:松开油门(暂停)但不熄火

通过这种精心设计的暂停机制,Android系统能够在界面切换时实现:

  • 流畅的动画过渡(60fps要求)
  • 合理的资源回收(内存节省30-50%)
  • 可靠的状态恢复(数据丢失率<0.01%)

理解这些底层机制,可以帮助开发者:

  1. 优化界面切换性能
  2. 避免ANR等稳定性问题
  3. 实现复杂的界面过渡效果
  4. 开发响应更快的沉浸式应用