冷启动是什么?先搞懂这玩意儿
说白了,冷启动就是你的 App 从零开始跑起来。不是从后台恢复那种,而是进程压根不存在,系统需要从头创建一个新进程。
我记得早些年刚做性能优化时,总觉得冷启动没什么大不了的。直到我接手了一个日活千万的项目,用户反馈说「打开App要等半天」……嗯,那次我才真正开始重视它。
冷启动的完整流程
一个完整的冷启动,从用户点击图标到看到第一个界面,大致走这么几步:
- 用户点击桌面图标 – Launcher 进程向系统服务发请求
- 系统创建新进程 – Zygote fork 出一个新进程,分配内存
- Application 对象初始化 – 创建 Application,回调
onCreate() - Activity 启动 – 创建目标 Activity,走完
onCreate()/onStart()/onResume() - 第一帧显示 – 内容渲染到屏幕上
核心要点: 冷启动的大部分时间花在进程创建和主线程初始化上。你写的 Application.onCreate() 越重,用户等得越久。
深入每个环节
1. 进程创建
用户点图标 → Launcher 通过 Binder 通知 ActivityManagerService → AMS 发现目标 App 进程不存在 → 请求 Zygote 进程 fork 一个子进程。
// 伪代码示意
AMS.sendStartActivityRequest(packageName);
if (process == null) {
Zygote.forkNewProcess(packageName);
// 分配进程空间,加载基础类
}
这个阶段大概会消耗 100ms~300ms,取决于设备性能和系统负载。我做过一次测试,在低端机上光是进程创建这一步就能干到 500ms+。
2. Application 初始化
新进程启动后,系统会先创建 Application 对象。注意,这里有个坑——很多开发者会在 onCreate() 里塞一堆第三方的初始化代码。
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// 以下代码全部在主线程执行!
initBugly()
initPush()
initIM()
initImageLoader()
initDatabase()
// …… 动辄十几二十个初始化
}
}
我曾经遇到一个案例: 项目里有个同事把所有的 SDK 初始化都堆在 Application.onCreate() 里,加起来跑了 1.2 秒。结果冷启动时长直接翻倍,用户差评一大堆。后来我们做了异步初始化 + 按需加载,才压回 500ms 以内。
这个阶段你可以考虑:
- 延迟初始化 — 不着急用的 SDK 扔到子线程
- 内容提供者初始化 — 利用
ContentProvider的自动初始化机制 - 启动预加载 — 提前加载 UI 需要用到的资源或数据
3. Activity 启动
Application 初始化完毕后,AMS 通知目标 Activity 创建。系统会依次调用:
Activity.onCreate()
Activity.onStart()
Activity.onResume()
这里面最耗时的往往是 onCreate() 里的 setContentView() 和布局解析。如果布局嵌套太深、或者用了太多自定义 View,那 inflate 时间就会指数级上升。
我的个人习惯: 在首页 Activity 里,尽量用 ViewStub 延迟加载不需要立刻显示的部分。另外,可以提前在 Application 初始化时预 Layout 一次,但要注意别喧宾夺主。
冷启动的三个阶段划分
| 阶段 | 起点 | 终点 | 典型耗时 |
|---|---|---|---|
| 进程创建 | 用户点击 | Application 构造完成 | 100ms~300ms |
| Application 初始化 | Application.onCreate() | 结束 | 200ms~1s |
| Activity 启动 | Activity.onCreate() | 第一帧显示 | 200ms~800ms |
你想想看,如果三个阶段都踩坑,冷启动时间轻轻松松突破 2 秒。对于用户来说,2 秒就足以让他关掉 App 了。
冷热启动的区别
顺便提一下热启动——其实就是 App 进程还在后台,直接恢复 Activity。这个过程基本只走 Activity 生命周期,不需要重新创建进程和 Application。
我做性能分析时,"热启动 < 200ms"是及格线,"冷启动 < 1.5s"是基础线。如果冷启动超过 2 秒,那一定要查优化空间了。
本章知识体系图
总结一句话
冷启动的本质就是从零搭建一个进程,然后跑起你的 App。这个过程里最耗时间的,往往不是你写的业务代码,而是各种「顺手写在 Application 里」的初始化操作。
下次你的项目冷启动慢了,别急着怀疑系统,先看看 Application.onCreate() 里到底塞了多少东西。我曾经见过一个项目,光打印日志就占了 200ms……嗯,你没看错,打印日志。