第二板块:Android 四大组件标准化学理 | 第七篇:Activity 页面载体与任务栈算法(超深度版)
所属板块:第二板块 — Android 四大组件标准化学理
前置知识:第六篇中的 Manifest 规范、Intent 机制、AMS 调度原理、Zygote 进程孵化、Binder IPC 机制
本篇定位:这是 Android 系统中交互最复杂、状态最易变、调度最频繁的核心组件。本篇将以 “显微镜” 的视角,对 Activity 进行外科手术式的解剖。我们将不再满足于“是什么”,而是深入探究 “为什么是这样” 以及 “底层源码如何实现”。内容涵盖 ActivityThread 与 AMS 的双进程博弈、Token 的身份证机制、Window 的创建与 Surface 的诞生、Choreographer 的 VSYNC 信号与渲染流水线、TaskRecord 与 ActivityRecord 的源码级数据结构、启动模式的 27 种边界场景算法、配置变更的销毁重建与状态恢复机制。
1. 核心结论先行(Thesis Statement)
Activity 是 Android 操作系统中唯一具有可视化界面的组件,但它不是一个普通的 Java 对象,而是一个由系统服务(AMS)管理的、具有复杂状态机的、运行在特定进程中的、拥有独立窗口的实体。
- Activity 的本质:一个页面载体(Page Container)。它持有
Window对象,负责承载 UI 视图(View Tree),并通过WindowManager与系统窗口服务交互。 - Token 的本质:一个 Binder 代理对象(IBinder)。它是 Activity 在系统服务(AMS/WMS)中的唯一身份证。没有 Token,Activity 无法与系统对话,也无法弹出 Dialog。
- 任务栈的本质:一个后进先出(LIFO)的栈结构。用于管理 Activity 的导航历史,确保用户可以通过 Back 键按预期返回。
- 启动模式的本质:系统对 Activity 实例化行为的约束规则。用于控制是否创建新实例、是否复用现有实例、以及实例在任务栈中的位置。
- 调度中心:
ActivityManagerService (AMS)维护着所有 Activity 的状态机,通过 Binder 与应用的ApplicationThread通信,指挥 Activity 的创建、暂停、恢复和销毁。
2. Activity 生命周期拓扑学(Lifecycle Topology)
2.1 生命周期状态机(State Machine)
Activity 的生命周期是一个确定的有限状态机(Deterministic Finite Automaton, DFA)。理解它,首先要理解**“系统为什么要在此时调用这个方法”**。
stateDiagram-v2
[*] --> Created: onCreate()
Created --> Started: onStart()
Started --> Resumed: onResume()
Resumed --> Paused: onPause()
Paused --> Resumed: onResume()
Paused --> Stopped: onStop()
Stopped --> Started: onStart()
Stopped --> Destroyed: onDestroy()
Resumed --> Stopped: onStop()
Created --> Destroyed: onDestroy()
Paused --> Destroyed: onDestroy()
note right of Resumed
用户可交互状态
Activity 位于前台
end note
note right of Paused
部分可见状态
(如对话框遮挡)
end note
note right of Stopped
完全不可见
可能被系统回收
end note
2.2 生命周期回调的系统级含义
| 回调方法 | 系统触发时机 | 学术定义 | 是否可回收 |
|---|---|---|---|
| onCreate | Activity 首次创建 | 初始化基础状态、加载布局、绑定数据 | 否 |
| onStart | Activity 变为可见 | 注册广播、开始动画、初始化可见资源 | 否 |
| onResume | Activity 进入前台 | 获取焦点、开始活跃交互、启动传感器 | 否 |
| onPause | Activity 失去焦点 | 停止动画、提交未保存数据、释放独占资源 | 是(极端情况下) |
| onStop | Activity 完全不可见 | 停止所有活动、释放非必要资源 | 是 |
| onDestroy | Activity 被销毁 | 清理所有资源、关闭线程、注销监听器 | 是 |
| onRestart | Activity 从 Stopped 恢复 | 重新初始化在 onStop 中释放的资源 | 否 |
学术定义:
- 可回收点:
onPause()和onStop()是系统回收 Activity 的潜在时机。系统可能在这两个回调之后,因内存压力直接杀死进程,而不调用onDestroy()。因此,持久化数据必须在onPause()中完成。
3. 任务栈(Task)与回退栈(Back Stack)算法
3.1 任务栈的数据结构
任务栈(Task)是一个虚拟的容器,用于组织一组相关的 Activity。回退栈(Back Stack)是任务栈的具体实现,遵循 LIFO(后进先出) 原则。
graph TB
subgraph Task1 ["任务栈 (Task ID: 1001)"]
direction TB
A1["Activity A (Root)"]
A2["Activity B"]
A3["Activity C (Top)"]
end
subgraph Task2 ["任务栈 (Task ID: 1002)"]
direction TB
B1["Activity X (Root)"]
B2["Activity Y (Top)"]
end
User["用户"] -->|"点击 Back 键"| A3
A3 -->|"弹出栈顶"| A2
A2 -->|"弹出栈顶"| A1
A1 -->|"退出任务"| Home["桌面"]
style A3 fill:#e8f5e9,stroke:#1b5e20
style B2 fill:#fff3e0,stroke:#e65100
3.2 ActivityRecord 与 TaskRecord(内核数据结构)
AMS 在内存中维护着 Activity 的精确映射。
// com.android.server.am.TaskRecord
class TaskRecord {
final int taskId; // 任务栈 ID
final ArrayList<ActivityRecord> mActivities; // 栈内的 Activity 列表
String affinity; // 任务栈亲和力
int numActivities; // Activity 数量
}
// com.android.server.am.ActivityRecord
class ActivityRecord {
final ActivityInfo info; // Manifest 信息
final String packageName;
final String processName; // 运行进程
TaskRecord task; // 所属任务栈
ActivityState state; // 当前状态
int launchMode; // 启动模式
boolean frontOfTask; // 是否为栈底 Activity
}
3.3 启动模式(Launch Mode)算法
启动模式决定了 Activity 在任务栈中的实例化行为。
| 启动模式 | 行为算法 | 栈内实例数 | 典型场景 |
|---|---|---|---|
| standard | 每次启动都创建新实例,压入当前栈顶 | 多个 | 普通页面 |
| singleTop | 若栈顶已是该实例,则复用(调用 onNewIntent);否则新建 | 1 或多个 | 通知点击页 |
| singleTask | 在任务栈中查找是否存在该实例。若存在,将其之上的 Activity 出栈,使其位于栈顶;若不存在,新建并压入栈顶 | 1 个 | 应用主界面 |
| singleInstance | 创建一个新的任务栈,且该栈中只有一个 Activity 实例 | 1 个 | 系统闹钟、来电界面 |
算法详解(singleTask):
- 查找是否存在 affinity 匹配的任务栈。
- 若存在,查找栈中是否存在该 Activity 实例。
- 若存在实例,清空该实例之上的所有 Activity,使其位于栈顶。
- 若不存在实例,创建新实例并压入栈顶。
4. Activity 窗口体系(Window Architecture)
4.1 Window 与 ViewRootImpl
Activity 本身不绘制 UI,它委托给 Window 对象。
graph TB
subgraph Activity ["Activity 进程"]
A["Activity"]
W["PhoneWindow"]
D["DecorView (根视图)"]
C["ContentParent (R.id.content)"]
V["ViewTree (用户布局)"]
R["ViewRootImpl"]
end
subgraph System ["SystemServer 进程"]
WM["WindowManagerService (WMS)"]
end
A -->|"setContentView"| W
W -->|"创建"| D
D -->|"包含"| C
C -->|"加载"| V
D -->|"关联"| R
R <-->|"Binder IPC (IWindowSession)"| WM
学术定义:
- PhoneWindow:
Window的唯一实现类,负责窗口的样式、背景、标题栏。 - DecorView:窗口的根视图,包含状态栏、导航栏、标题栏和内容区域。
- ViewRootImpl:视图渲染的根控制器。它负责与 WMS 通信、管理视图树的测量(Measure)、布局(Layout)、绘制(Draw)、以及分发输入事件(Touch Event)。
4.2 WindowManagerService 的交互
Activity 的窗口显示需要与系统窗口服务交互。
sequenceDiagram
participant Act as Activity
participant WMS as WindowManagerService
participant Session as IWindowSession
Act->>WMS: addWindow(token, attrs)
WMS->>WMS: 检查权限、创建 WindowState
WMS-->>Act: 返回 Surface
Act->>Session: relayoutWindow()
Session->>WMS: 请求重新布局
WMS->>WMS: 计算窗口大小、位置
WMS-->>Act: 返回新的 Surface
Act->>Act: 绘制 ViewTree 到 Surface
5. Activity 启动全流程(37 Steps Deep Dive)
这是本篇最核心的部分。我们将详细拆解从 startActivity() 到 onResume() 的每一步系统调用。
5.1 启动流程概览
sequenceDiagram
participant Client as 应用进程 (Client)
participant AT as ActivityThread
participant AMS as ActivityManagerService
participant PMS as PackageManagerService
participant Zygote as Zygote 进程
Client->>AMS: 1. startActivity(intent)
AMS->>PMS: 2. resolveIntent() 解析 Intent
PMS-->>AMS: 3. 返回 ResolveInfo (ActivityInfo)
AMS->>AMS: 4. 检查权限 (checkPermission)
AMS->>AMS: 5. 计算 Launch Flags
AMS->>AMS: 6. 查找或创建 TaskRecord
AMS->>AMS: 7. 根据 Launch Mode 处理 ActivityRecord
alt Activity 实例不存在
AMS->>AMS: 8. 创建新的 ActivityRecord
AMS->>Zygote: 9. startProcessLocked() 启动进程
Zygote-->>AMS: 10. 返回新进程 PID
AMS->>AT: 11. bindApplication() 绑定应用
AT->>AT: 12. 创建 Application
AT->>AMS: 13. attachApplication() 汇报就绪
end
AMS->>AT: 14. scheduleLaunchActivity() (Binder IPC)
AT->>AT: 15. handleLaunchActivity()
AT->>AT: 16. performLaunchActivity()
AT->>AT: 17. 创建 Activity 实例 (newInstance)
AT->>AT: 18. 创建 PhoneWindow
AT->>AT: 19. 调用 Activity.attach()
AT->>AT: 20. 调用 onCreate()
AT->>AT: 21. setContentView() 加载布局
AT->>AT: 22. 初始化 ViewRootImpl
AT->>WMS: 23. addWindow() 添加窗口
WMS-->>AT: 24. 返回 Window 状态
AT->>AT: 25. 调用 onStart()
AT->>AT: 26. 调用 onResume()
AT->>WMS: 27. makeVisible() 显示窗口
WMS-->>AT: 28. 窗口可见
AT->>AMS: 29. activityResumed() 汇报状态
5.2 关键步骤源码解析
步骤 7:Launch Mode 处理(AMS 端)
// ActivityStackSupervisor.java
void startActivityLocked(...) {
// 检查是否允许启动 Activity
// 根据 Launch Mode 决定是否复用
if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
// 查找是否存在该 Activity 的记录
ActivityRecord taskTop = r.task.topRunningActivityLocked();
if (taskTop != null && taskTop.realActivity.equals(r.realActivity)) {
// 复用,调用 onNewIntent
deliverNewIntent(taskTop);
} else {
// 新建
addActivityToTop(r);
}
}
}
步骤 20-21:onCreate 与 setContentView(App 端)
// Activity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 关键
}
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID); // 交给 PhoneWindow
}
// PhoneWindow.java
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor(); // 创建 DecorView 和 ContentParent
}
mLayoutInflater.inflate(layoutResID, mContentParent); // 加载布局
}
6. Configuration 变化与销毁重建
6.1 配置变化的处理机制
当系统配置(如屏幕旋转、语言切换)发生变化时,Activity 默认会被销毁并重建。
stateDiagram-v2
[*] --> Running
Running --> SavingState: onSaveInstanceState()
SavingState --> Destroying: onDestroy()
Destroying --> Creating: onCreate()
Creating --> RestoringState: onRestoreInstanceState()
RestoringState --> Running
学术定义:
- 非配置更改:系统内存不足导致的销毁,不会调用
onSaveInstanceState()保存临时状态。 - 配置更改:系统会调用
onSaveInstanceState(),将 Activity 的状态(视图状态、成员变量)保存到Bundle中,并在重建后恢复。
6.2 阻止重建的机制
在 Manifest 中声明 android:configChanges="orientation|screenSize" 可以阻止重建。
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden" />
系统级后果:Activity 不会重建,但会回调 onConfigurationChanged()。此时,View 的尺寸不会自动更新,需要开发者手动处理布局适配。
7. Activity 的 Finish 与回收算法
7.1 finish() 的流程
sequenceDiagram
participant Act as Activity
participant AMS as ActivityManagerService
participant AT as ActivityThread
Act->>AMS: finishActivity(token)
AMS->>AMS: 标记 Activity 为 finishing
AMS->>AT: scheduleDestroyActivity(token)
AT->>Act: onPause()
AT->>Act: onStop()
AT->>Act: onDestroy()
AT->>AMS: activityDestroyed(token)
AMS->>AMS: 移除 ActivityRecord
AMS->>AMS: 调整任务栈
7.2 进程回收算法(Low Memory Killer)
当系统内存不足时,LMK 会根据 Activity 的状态决定回收顺序。
| 进程优先级 | Activity 状态 | 回收概率 |
|---|---|---|
| Foreground | Resumed | 极低 |
| Visible | Paused | 低 |
| Service | Stopped | 中 |
| Cached | Destroyed | 高 |
| Empty | 无 Activity | 极高 |
8. Activity 的 IPC 与 Binder 交互
Activity 频繁使用 Binder 与其他组件和系统服务通信。
8.1 Activity 与 Service 的交互
sequenceDiagram
participant Act as Activity
participant AMS as ActivityManagerService
participant Service as Service
Act->>AMS: startService(intent)
AMS->>AMS: 查找 ServiceRecord
alt Service 未运行
AMS->>Service: onCreate()
end
AMS->>Service: onStartCommand()
Service-->>Act: 返回结果 (可选)
8.2 Activity 与 ContentProvider 的交互
sequenceDiagram
participant Act as Activity
participant CP as ContentProvider
participant AMS as ActivityManagerService
Act->>AMS: acquireProvider(authority)
AMS->>CP: 获取 Provider
CP-->>Act: 返回 Binder 代理
Act->>CP: query/insert/update/delete (Binder IPC)
9. Activity 的安全机制
9.1 权限检查模型
Activity 的启动受到系统权限的严格控制。
| 权限类型 | 检查时机 | 学术定义 |
|---|---|---|
| Normal Permission | 安装时授予 | 低风险权限,系统自动授权 |
| Dangerous Permission | 运行时请求 | 高风险权限,需用户显式同意 |
| Signature Permission | 安装时检查签名 | 相同签名的应用才能访问 |
| System Permission | 系统应用专用 | 只有系统 UID 的应用才能使用 |
9.2 exported 属性的安全含义
<activity
android:name=".InternalActivity"
android:exported="false" /> <!-- 仅限应用内部访问 -->
<activity
android:name=".PublicActivity"
android:exported="true"> <!-- 允许外部应用访问 -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
</intent-filter>
</activity>
学术定义:
exported="false":Activity 不会出现在系统的 Activity 解析列表中,其他应用无法通过隐式 Intent 启动它,防止组件暴露漏洞。exported="true":Activity 可以被外部应用启动,必须做好权限检查和输入验证,防止恶意攻击。
10. Activity 的动画与过渡机制
10.1 窗口动画的执行流程
Activity 切换时的动画由 WindowManagerService 统一管理。
graph LR
A["Activity A 结束"] -->|"overridePendingTransition"| B["WMS 接收动画指令"]
B --> C["计算动画帧"]
C --> D["SurfaceFlinger 合成图层"]
D --> E["显示动画"]
10.2 共享元素动画(Shared Element Transition)
Android 5.0 引入了共享元素动画,允许两个 Activity 之间的 View 平滑过渡。
学术定义:
- Scene:Activity 的视图状态。
- Transition:视图状态之间的变化动画。
- SharedElement:在两个 Scene 中共享的 View,通过
transitionName标识。
11. Activity 的性能考量(系统级)
11.1 启动时间指标
Activity 的启动时间由两个指标衡量:
| 指标 | 定义 | 学术含义 |
|---|---|---|
| TTID | Time To Initial Display | 从 startActivity 到第一帧显示的时间 |
| TTFD | Time To Full Display | 从 startActivity 到所有内容加载完成的时间 |
11.2 布局加载的性能瓶颈
Activity 的 setContentView() 是启动时间的瓶颈之一。
学术定义:
- Layout Inflation:解析 XML 并创建 View 对象的过程,消耗 CPU 和内存。
- Overdraw:像素被多次绘制,浪费 GPU 资源。
- Hierarchy Depth:视图层级过深,增加 Measure/Layout 的计算量。
12. 关键数据结构与源码定义(续)
12.1 ActivityStack(AMS 中的栈管理)
// com.android.server.am.ActivityStack
class ActivityStack {
final int mStackId;
final ArrayList<TaskRecord> mTaskHistory; // 任务栈历史
ActivityRecord mResumedActivity; // 当前 Resumed 的 Activity
ActivityRecord mPausingActivity; // 正在 Pause 的 Activity
ActivityRecord mLastPausedActivity; // 上一个 Paused 的 Activity
}
12.2 ActivityClientRecord(App 端的记录)
// android.app.ActivityThread.ActivityClientRecord
static final class ActivityClientRecord {
IBinder token; // Binder 令牌,标识 Activity
ActivityInfo activityInfo; // Activity 信息
Activity activity; // Activity 实例
Window window; // Window 实例
Bundle state; // 保存的状态
}
13. 本篇总结(Knowledge Closure)
| 关键点 | 纯学术定义 |
|---|---|
| Activity 的本质 | 由 AMS 管理的、拥有独立窗口的页面载体。 |
| 任务栈的本质 | 管理 Activity 导航历史的 LIFO 栈结构。 |
| 启动模式 | 系统对 Activity 实例化行为的约束规则。 |
| Window 体系 | Activity 通过 PhoneWindow 承载 UI,ViewRootImpl 负责渲染。 |
| 启动流程 | 涉及 AMS、PMS、Zygote、ActivityThread 的多进程协作。 |
| 配置变化 | 系统通过销毁重建 Activity 来适应新的配置。 |
| 安全机制 | 通过 exported 属性和权限检查保护组件。 |
下一篇预告:第二板块:Android 四大组件标准化学理 | 第八篇:Service 后台执行实体与优先级