本文是对 Android 中startActivity启动流程的深度解析,基于 Android 6.0 源码,详细梳理了从点击启动到 Activity 生命周期回调的完整过程。以下用通俗语言和结构化逻辑描述核心内容:
一、启动流程总览
startActivity的本质是跨进程通信(IPC)和系统服务协同工作的过程,主要涉及三类角色:
-
调用者进程(如 Launcher):发起启动请求。
-
系统服务进程(system_server) :通过
ActivityManagerService(AMS)管理 Activity 的生命周期和任务栈。 -
目标进程:创建并显示目标 Activity。
核心步骤:
- 调用者进程通过 Binder 向 AMS 发送启动请求。
- AMS 检查权限、解析目标 Activity 信息,决定是否创建新任务栈或复用现有栈。
- 目标进程不存在时,通过 Zygote fork 新进程;存在时直接通知目标进程启动 Activity。
- 目标进程通过 Handler 机制回调 Activity 生命周期方法(如
onCreate)。
二、关键流程详解
1. 应用层发起请求(调用者进程)
当在 Activity 中调用startActivity(intent)时,实际会经过以下步骤:
-
Activity.startActivityForResult:
调用Instrumentation.execStartActivity,该方法通过ActivityManagerNative.getDefault()获取ActivityManagerProxy(AMP)—— 这是 AMS 的Binder 客户端代理。 -
AMP 通过 Binder 发送请求到 AMS:
通过transact方法跨进程调用 AMS 的startActivity方法,传递 Intent、调用者包名等参数。
通俗比喻:
调用者进程像 “客户”,AMS 像 “服务台”,Binder 通信就是 “客户” 通过 “电话” 向 “服务台” 提交请求。
2. 系统服务层处理请求(system_server 进程)
AMS 是 Android 系统的核心服务,负责管理所有 Activity 的生命周期和任务栈。以下是关键环节:
2.1 解析目标 Activity 信息
ActivityStackSupervisor(ASS).resolveActivity:
通过PackageManagerService(PMS)查询系统中匹配 Intent 的 Activity 信息(如ActivityInfo)。若存在多个匹配项,会弹出选择对话框(如分享功能的应用选择)。- 权限检查:
检查调用者是否有权限启动目标 Activity,如声明了android:permission属性的 Activity 需验证权限。
2.2 任务栈(Task)管理
-
任务栈的作用:
管理 Activity 的堆叠顺序,一个任务栈可包含多个属于同一应用或不同应用的 Activity。 -
启动模式(Launch Mode)的影响:
- standard(默认) :每次启动都创建新实例,放入当前任务栈。
- singleTop:若栈顶已是目标 Activity,直接复用(不创建新实例)。
- singleTask:若栈中存在目标 Activity,清除其上方的所有 Activity,使其成为栈顶。
- singleInstance:创建独立任务栈,该 Activity 独占一个栈。
-
Flags 的作用:
例如FLAG_ACTIVITY_NEW_TASK会使 Activity 在新任务栈中启动(类似浏览器新建标签页)。
2.3 处理任务栈切换与暂停
- 暂停当前 Activity:
若启动新 Activity 时,当前栈顶 Activity 未暂停(如处于RESUMED状态),AMS 会先调用schedulePauseActivity暂停它。 - 任务栈调度:
通过ActivityStack管理栈内 Activity 的顺序,确保前台 Activity 始终可见。若目标 Activity 属于后台任务栈,会将其移至前台(类似切换浏览器标签页)。
2.4 启动目标进程
- 进程存在检查:
通过ProcessRecord判断目标 Activity 所属进程是否存在。若不存在,调用AMS.startProcessLocked通过 Zygote 创建新进程。 - Zygote 的作用:
作为 Android 进程的 “孵化器”,Zygote 预加载系统资源,fork 出的新进程可快速启动(类似模板复制)。
3. 目标进程初始化 Activity(目标进程)
当目标进程创建或唤醒后,通过以下步骤启动 Activity:
-
ApplicationThread.scheduleLaunchActivity:
AMS 通过ApplicationThreadProxy(ATP)(目标进程的 Binder 代理)调用目标进程的scheduleLaunchActivity,传递 Activity 信息。 -
Handler 消息机制:
目标进程的主线程(ActivityThread)通过 Handler 接收H.LAUNCH_ACTIVITY消息,触发handleLaunchActivity方法。 -
创建 Activity 实例:
通过反射创建 Activity 对象,调用attach方法关联上下文(Context),并依次调用生命周期方法:java
onCreate() → onStart() → onResume()至此,Activity 界面渲染完成,用户可见。
三、核心概念与常见问题
1. 任务栈与 ActivityRecord
ActivityRecord:代表一个 Activity 实例的状态,包含组件信息、任务栈归属等。- 任务栈的唯一性:每个 ActivityRecord 必须属于一个任务栈(
TaskRecord),任务栈通过ActivityStack管理,确保同一时刻只有一个栈处于前台。
2. 跨进程通信(IPC)的关键组件
-
Binder:Android 的核心 IPC 机制,用于进程间数据传输。
- 客户端:调用者进程的
ActivityManagerProxy(AMP)。 - 服务端:system_server 进程的
ActivityManagerService(AMS)。
- 客户端:调用者进程的
-
Handler:目标进程通过 Handler 将 IPC 回调切换到主线程,保证 UI 操作的线程安全。
3. 常见异常与处理
START_INTENT_NOT_RESOLVED:Intent 无法匹配到任何 Activity(如组件名错误)。START_PERMISSION_DENIED:调用者缺少启动目标 Activity 的权限。- 任务栈混乱:错误使用启动模式或 Flags 导致 Activity 堆叠异常(如 singleTask 未配合
FLAG_ACTIVITY_CLEAR_TOP)。
四、总结:启动流程时序图
plaintext
调用者进程(如Launcher) system_server进程 目标进程
┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐
│ startActivity() │────── Binder ───────►│ AMS.startActivity() │ │ │
│ │ │ │←───── 创建进程 ───│ Zygote fork │
│ │ │ ASS.resolveActivity() │ │ │
│ │ │ ASS.startActivityLocked()│ │ │
│ │ │ │───── Binder ─────►│ ApplicationThread │
│ │ │ │ │ scheduleLaunchActivity() │
│ │ │ │←──── 消息机制 ────│ Handler(H.LAUNCH_ACTIVITY) │
└───────────────────────┘ └───────────────────────┘ │ │
└───────────────────────┘
▼
Activity.onCreate()
五、开发建议
-
合理使用启动模式:根据业务需求选择
Launch Mode(如登录页用 singleTask 避免重复实例)。 -
避免内存泄漏:非必要情况下,避免在 Activity 中持有跨进程的长生命周期对象(如 AMS 的引用)。
-
权限与兼容性:动态检查权限(如 Android 6.0 + 的运行时权限),确保不同设备和系统版本的兼容性。
通过理解startActivity的底层流程,开发者可更精准地优化应用启动性能、解决任务栈异常等问题,提升用户体验。