Android App 启动原理
Android 中说的App 启动原理,本质上是在回答一个问题:
当我们点击桌面图标后,一个应用是如何从“还没运行”到“页面显示出来”的?
这个过程会涉及:
- Launcher(桌面应用)
- AMS(
ActivityManagerService) - Zygote
- 应用进程创建
ActivityThreadApplication- 启动目标
Activity
如果从整体上看,可以先记住这一条主线:
点击桌面图标 -> Launcher 发起启动请求 -> AMS 校验和调度 -> Zygote fork 新进程 -> 应用进程启动 -> 创建 Application -> 启动 Activity -> 页面显示
1. 先理解什么叫“App 启动”
通常我们说 App 启动,分成两类:
- 冷启动:应用进程不存在,需要新建进程
- 热启动:应用进程已经存在,只是把界面重新切回前台
- 温启动:进程还在,但需要重新创建
Activity
面试里最常问、也最重要的是:冷启动流程。
因为冷启动把 Android 框架里最核心的一整套机制都串起来了。
2. 点击图标后,第一步发生了什么
用户点击桌面图标时,真正响应点击事件的是Launcher,也就是桌面程序。
Launcher 本身也是一个普通 Android 应用,只不过它承担了桌面和应用入口的职责。
点击图标后,Launcher 会拿到目标应用的Intent信息,然后调用启动流程,本质上会发起一次startActivity()请求。
这时候事情还没有直接交给目标 App,而是先进入系统服务。
也就是说:
- Launcher 不负责真正创建目标应用进程
- 真正的启动调度者是系统服务
- 这个核心服务就是
AMS
3. AMS 在启动流程中的作用
AMS全称是ActivityManagerService,它是 Android 中负责组件调度和进程管理的核心系统服务之一。
当 Launcher 发起启动请求后,AMS 会做几件关键事情:
- 校验目标
Activity是否存在、是否可启动 - 检查目标应用进程是否已经存在
- 如果进程不存在,就创建应用进程
- 进程创建完成后,再通知应用去启动目标
Activity
所以 AMS 的角色可以理解成:
它不直接画页面,但它负责把“该由谁启动、何时启动、在哪个进程启动”安排清楚。
4. 如果进程不存在,就需要创建进程
这一步是冷启动的核心。
Android 不会让每个应用随意自己创建进程,而是通过Zygote来统一孵化应用进程。
4.1 什么是 Zygote
Zygote是 Android 系统中非常关键的一个进程,可以理解成“应用进程的模板进程”。
它会提前完成很多通用初始化工作,比如:
- 启动虚拟机
- 加载系统类
- 预加载常用资源
这样做的好处是:
- 后续创建应用进程更快
- 通过
fork机制复用父进程资源,减少内存开销
4.2 AMS 如何让 Zygote 创建进程
当 AMS 发现目标 App 进程还没启动时,会向Zygote发送创建进程请求。
然后Zygote通过fork()创建出一个新的应用进程。
这个新进程创建出来后,就拥有了独立的:
- 进程空间
- 虚拟机环境
- 主线程
到这里,应用已经不再只是“一个安装包”,而是变成了“一个真正运行中的 Linux 进程”。
5. 新进程启动后,谁来接管应用主线程
新进程被创建后,并不是马上就显示页面,而是会先进入应用自己的运行入口。
这个入口对应的核心类是:
ActivityThread
很多人容易误解,名字里带了Thread,就以为它只是一个线程类。实际上它更像是:
应用进程主线程的管理者。
它负责在应用进程里完成很多关键工作,比如:
- 创建主线程消息循环
- 和 AMS 进行通信
- 创建
Application - 创建并启动
Activity
可以简单理解为:
AMS 负责“系统侧调度”,ActivityThread负责“应用侧落地执行”。
6. Application 是什么时候创建的
在启动目标Activity之前,系统会先创建应用级别的对象,也就是Application。
典型流程是:
- 创建
LoadedApk等运行环境信息 - 创建应用的
Context - 通过反射创建
Application实例 - 回调
Application#onCreate()
这也是为什么我们经常会在Application#onCreate()中做一些全局初始化,比如:
- 日志框架初始化
- 路由初始化
- 网络库初始化
- 崩溃监控初始化
但是要注意:
这里的代码越重,冷启动就越慢。
因为Application还没走完,首页通常也还没真正显示出来。
7. Activity 是如何被启动出来的
当应用进程准备好之后,AMS 会通知应用进程去启动目标Activity。
应用进程中的ActivityThread收到消息后,会执行对应的启动流程,大致包括:
- 创建
Activity实例 - 创建
Context - 关联
PhoneWindow - 调用
Activity#attach() - 依次回调生命周期方法
常见启动顺序通常是:
onCreate()onStart()onResume()
在onCreate()中,一般会执行:
setContentView()- 初始化 View
- 初始化数据
- 注册监听器
当界面完成测量、布局、绘制后,用户才真正看到页面。
8. 从源码视角看启动链路
如果从高层源码链路去记,可以抓住下面这条主干:
- Launcher 发起
startActivity() - 请求进入系统进程中的
AMS - AMS 判断目标进程是否存在
- 不存在则请求
Zygotefork 新进程 - 新进程启动后进入
ActivityThread.main() - 创建
Application ActivityThread收到启动Activity的消息- 创建并回调目标
Activity - 完成页面绘制,启动结束
这条链路不要求每一步都背源码细节,但至少要知道:
- 谁发起请求
- 谁负责调度
- 谁负责创建进程
- 谁负责在应用侧执行生命周期
9. 为什么冷启动会慢
冷启动慢,本质上是因为它要做的事情太多,而且很多事情都集中在主线程早期阶段。
常见耗时点包括:
- 进程创建本身有成本
Application#onCreate()做了太多初始化- 首页
Activity#onCreate()逻辑太重 - 首屏布局层级太深,绘制耗时高
- 同步 I/O、数据库、网络阻塞主线程
- SDK 初始化过多
可以理解成:
冷启动慢,不一定慢在“启动框架流程”,更常见的是慢在业务初始化代码。
10. 启动优化一般优化什么
做启动优化时,核心目标是:
让首屏更早可见,让主线程更少阻塞。
常见优化方向有:
- 延迟初始化非核心组件
- 按优先级拆分初始化任务
- 异步执行耗时任务
- 减少首页布局复杂度
- 避免主线程 I/O
- 使用启动器或任务编排框架统一管理初始化顺序
例如:
- 统计、埋点、更新检查可以延后
- 不影响首屏的 SDK 可以放到子线程
- 首屏只加载最必要的数据
11. 面试中可以怎么概括
如果面试官让你简单介绍 App 启动原理,可以这样回答:
Android App 启动本质上是从 Launcher 点击图标开始,Launcher 通过系统服务发起启动请求,AMS 负责统一调度;如果目标进程不存在,AMS 会通知 Zygote fork 出新的应用进程。新进程启动后会进入ActivityThread,先创建Application,再创建并启动目标Activity,最终完成页面绘制,用户看到首页。
如果面试官继续追问,可以继续往下展开:
- 冷启动、热启动、温启动的区别
Zygote为什么能加快启动Application和Activity的创建顺序- 启动优化一般优化哪些点
12. 一张简化流程图
可以把整个过程记成下面这张图:
Launcher -> AMS -> Zygote -> App Process -> ActivityThread -> Application -> Activity -> View 显示
13. 一句话总结
App 启动原理的核心,就是系统先决定“要不要创建进程”,再由应用进程完成Application和Activity的创建,最后把页面绘制出来。
如果只记 3 个关键词,可以记:
AMS:负责调度Zygote:负责创建进程ActivityThread:负责在应用进程中执行启动流程
推荐面试题点我传送 链接:
https://www.toutiao.com/article/7629148616564818484/?log_from=2a3e05473a27c_1776384210421