App启动流程
Android App 启动流程是系统与应用协同工作的过程,按启动方式可分为 冷启动(首次启动,进程未创建)、热启动(进程已存在,仅重启 Activity)和 温启动(进程存在但 Activity 需重建),其中 冷启动流程最完整,也是优化的重点。以下以冷启动为例,详解从点击图标到界面显示的全流程:
冷启动核心流程(7 个关键步骤)
冷启动是 App 进程从无到有的过程,涉及 系统层(Zygote、AMS) 和 应用层(Application、Activity) 交互,步骤如下:
1. 用户触发启动(点击图标)
用户点击 Launcher(桌面)上的 App 图标,Launcher 进程通过
Intent向系统发送启动请求:// Launcher 内部逻辑(简化) Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setComponent(new ComponentName(packageName, activityName)); // 目标 App 的入口 Activity startActivity(intent);
2. 系统层:AMS 接收并分配任务
AMS(ActivityManagerService)
是系统核心服务,负责管理所有 Activity 生命周期。收到 Launcher 的请求后,AMS 会:
- 检查目标 App 的进程是否已存在:冷启动时进程不存在,进入下一步。
- 为 App 分配 任务栈(Task Stack):每个 App 有独立任务栈,用于管理 Activity 跳转顺序。
- 向 Zygote 进程 发送创建新进程的请求。
3. 系统层:Zygote 孵化 App 进程
- Zygote 是 Android 系统的 “进程孵化器”,所有 App 进程都是 Zygote 的子进程:
- Zygote 接收 AMS 的请求后,通过
fork()系统调用创建新的 App 进程(pid唯一)。 - 新进程继承 Zygote 的预加载资源(如 Android 框架类、常用库),避免重复加载,加快进程启动。
- 新进程启动后,会创建 ActivityThread(应用主线程的管理类,即 UI 线程),并调用其
main()方法,标志 App 进程正式启动。
- Zygote 接收 AMS 的请求后,通过
4. 应用层:初始化 Application 类
ActivityThread 的
main()方法中,会先初始化 Application实例(全局唯一),执行以下逻辑:
创建
Application对象:通过反射调用Application的无参构造函数。调用
attachBaseContext(Context):初始化 Context 基础信息(如资源管理器、包信息),早于onCreate()。调用
onCreate():执行 App 全局初始化逻辑(如第三方 SDK 初始化、全局变量赋值、网络 / 数据库配置)。⚠️ 注意:
onCreate()运行在主线程,若执行耗时操作(如网络请求、大量计算),会直接导致启动延迟(黑白屏时间变长)。
5. 应用层:初始化入口 Activity
Application 初始化完成后,ActivityThread 开始初始化
入口 Activity
(即 Manifest 中配置
<category android:name="android.intent.category.LAUNCHER"/>的 Activity):- 创建 Activity 对象:反射调用 Activity 的无参构造函数。
- 执行 Activity 生命周期的早期方法:
attach(Context):绑定 Context,初始化 Window、PhoneWindow 等组件。onCreate(Bundle):执行 Activity 初始化逻辑,核心是setContentView(R.layout.xxx)(加载布局)。onStart():Activity 进入 “可见但不可交互” 状态。onResume():Activity 进入 “可见且可交互” 状态,此时系统开始绘制界面。
6. 绘制界面(首次绘制:First Draw)
onResume()后,系统触发UI 绘制流程
(Measure → Layout → Draw):
- Measure:计算 View 树中每个 View 的宽高(如
match_parent对应父 View 尺寸)。 - Layout:确定每个 View 在屏幕上的位置(坐标)。
- Draw:将 View 树绘制到屏幕(通过 Canvas 绘制背景、文字、图片等)。
首次绘制完成后,App 界面正式显示在屏幕上,标志 “冷启动完成”。
⚠️ 注意:从 “点击图标” 到 “首次绘制” 的时间,称为冷启动耗时,是性能优化的核心指标(目标 < 2 秒)。
- Measure:计算 View 树中每个 View 的宽高(如
7. 后续生命周期(可选)
- 界面显示后,Activity 会继续执行后续生命周期方法(如
onPostResume()),此时用户可与 App 交互(如点击按钮、滑动列表)。
热启动与温启动流程(简化版)
冷启动是 “全流程”,热启动和温启动因进程已存在,流程更短:
| 启动类型 | 核心特点 | 流程简化 | 耗时对比 |
|---|---|---|---|
| 热启动 | 进程、Application、Activity 均存在 | 点击图标 → AMS 唤起 Activity → onResume() | 最快(< 500ms) |
| 温启动 | 进程、Application 存在,Activity 需重建 | 点击图标 → 重建 Activity(onCreate() → onResume()) | 中等(500ms~1s) |
| 冷启动 | 进程、Application、Activity 均需创建 | 全流程(7 步) | 最慢(1~3s) |
关键注意点(影响启动速度的核心环节)
- Zygote 预加载:系统预加载框架类和资源,减少 App 进程初始化时间,开发者无法干预。
- Application.onCreate():主线程耗时操作(如 SDK 初始化)是启动延迟的主要原因,需异步 / 延迟处理。
- Activity.onCreate():
setContentView()加载复杂布局(如嵌套层级多、大图片)会增加绘制耗时,需简化布局。 - 首次绘制(First Draw):只有完成首次绘制,用户才能看到界面,之前的 “黑白屏” 是系统的临时过渡窗口(见「App 黑白屏问题」)。
启动流程总结
冷启动流程可概括为:
用户点击 → 系统 AMS 调度 → Zygote 孵化进程 → 初始化 Application → 初始化 Activity → 绘制界面 → 交互
核心是 “系统层创建进程 → 应用层初始化组件 → 界面绘制” 三个阶段,优化启动速度需重点关注应用层的 Application 和 Activity 初始化,避免主线程耗时操作,同时通过自定义过渡窗口优化用户感知。