本文参考了目前大部分 Android 应用启动优化的方案,将大家的方案做一个汇总,如果你有这方面的需求,只需要对照这篇文章,看看其他人的方案,查漏补缺。很多方案是要根据具体的业务去做优化的,所以这里也没有对每一种方案进行详细的介绍,要用到哪一个方案的时候,可以具体去网上查找对应方案的具体实现方法,这里只是做一个汇总
另外我还加上了部分系统厂商所做的启动相关的优化,不过只写了一些我知道的,还有一些厂商有黑科技,就不在这里的讨论范围了。知道厂商做的事情,可能也会帮助到你,比如联系厂商做白名单、接入厂商 SDK 等
版本说明(2026-10-13 核查):本文原发于 2019 年,保留当年的案例和优化分类。冷、温、热启动、测量指标与系统启动页已按新版文档补充;厂商白名单、预测和重启策略仅作历史线索,不能当作所有设备共有的能力。Android 10 / 16 的进程池与调度相关说明以版本化源码为准。
现在做启动优化,先固定“何时算启动完成”:首帧、首屏内容和可交互并不相同。用 Macrobenchmark 重复测量关键入口,结合 Perfetto 查主线程、RenderThread、Binder、I/O 和 GC;线上再按设备与版本观察启动分布及稳定性。Baseline Profiles 用于指导 ART 编译,Startup Profiles 用于构建时的 DEX 布局,两者不能混为同一种编译优化。
应用启动概述
应用启动的一般流程
从桌面点击图标到主界面可操作,会经过系统调度、必要的进程/组件初始化、UI 构建与内容加载。下面是旧版简图,只画出了部分阶段:

- SystemServer 协调进程启动、Activity 与窗口管理;需要普通 App 进程时会请求 Zygote 派生或使用可用的 USAP,并不是由 SystemServer 自己直接 fork App。
- App 进程 在主 Looper 已建立后处理应用绑定、Provider 初始化、
Application.onCreate()和 Activity 等工作。不是每次启动都要创建四大组件;Service、Receiver 等取决于入口与业务。
图中把 Application.onCreate 画在 MainThread 框外,不能据此理解成它运行在其他线程,或执行完它才创建主线程。首帧画出之后,网络内容和可交互状态也可能仍未准备好。
冷启动和热启动
还需要补上原文遗漏的 温启动。按常见进程/Activity 状态理解:
- 冷启动(cold):需要启动 App 进程,执行应用与界面的初始化。
- 温启动(warm):典型情况是进程仍在,但目标 Activity 需要重新创建,执行
onCreate()等流程。 - 热启动(hot):已有 Activity 实例及界面状态可复用,主要是恢复到前台;仍可能有恢复内容、布局或绘制工作。
Back、Home 不是可靠的分类开关:Activity 的状态和版本行为可能不同,后台进程也可能已被回收。最近任务列表里的卡片更不能证明进程仍存活。测量时记录进程是否重建、Activity 是否重建,并以工具对 cold / warm / hot 的定义为准。参见 启动状态说明。
启动速度的测量
各家应该都有自己的方案,关键在于如何定义启动结束的点,这也是一直困扰我的一个地方。复杂页面需要明确可观察的结束条件,不能只选一个看起来更小的数字。
- TTID:目标页面首帧显示的时间,系统可以观测;首帧可能还只是骨架或加载状态。
- TTFD:App 在主要内容就绪后通过
reportFullyDrawn()或相应的 ReportDrawn API 报告。它取决于业务定义与上报时机,不会自动证明所有交互都正确。 - 可交互/业务完成:例如列表能点击、登录完成,需要另外定义场景和断言。OCR 能辅助识别目标内容,但文字出现不保证图片加载完成或按钮已可操作。
Macrobenchmark 的 StartupTimingMetric 提供 timeToInitialDisplayMs 和 timeToFullDisplayMs;后者关联 fully-drawn 信号所在或之后的相应渲染帧,不能把没有上报的结果填成 0。固定 release 构建、启动模式、编译/Profile 状态、登录与数据状态,在真实设备重复采样,比较分布,同时保留 Trace。基准工程配置见 Macrobenchmark 指南。
adb shell am start -W 仍适合快速诊断,但输出字段有版本差异:旧版常见 ThisTime/TotalTime/WaitTime;AOSP Android 16 输出 LaunchState、TotalTime、WaitTime,不再输出 ThisTime。WaitTime 也不是首屏内容或纯 App CPU 时间。一次命令或一次录屏都不能替代稳定的发布基准。
原文参考的 手淘全链路性能优化 提倡自动化、稳定和持续集成,并用 OCR 识别页面。这里保留方法线索,不把其 OCR 服务识别率当成当前 App 启动终点识别的准确率。
App 优化
启动窗口优化
系统 StartingWindow、Android 12 的 SplashScreen,以及 App 自己的 SplashActivity 是不同的东西。启动页能改善等待反馈,但不能替代实际初始化优化。
- 对旧版主题预览窗口,避免无必要地用
android:windowDisablePreview="true"造成无内容等待;主题背景尽量与进入后的界面一致。 - Android 12(API 31)起,系统在冷/温启动使用标准 SplashScreen。按 官方迁移指南 配置主题与 API;旧背景大图和禁用预览的技巧不能当作新版通用方案。保留额外 SplashActivity 还可能导致连续两次闪屏。
- 能直接路由到目标 Activity 时减少无意义的中转。登录、深链和广告有业务约束,应分别测量,不要为了“只有一次跳转”破坏状态恢复。
原文提到微信、知乎、抖音的配置属于当时观察,缺少可复核的版本与白名单证据,不能据此断言这些应用现在如何配置或很少冷启动。
线程优化
线程优化要控制同时运行的工作与依赖等待。可运行线程过多可能增加主线程的 Runnable 等待;Sleep 则还可能来自锁、条件变量、Binder 或正常空闲,不能全部归因于 CPU 不够。
- 按任务类型限制线程池并发与队列积压,线程池本身不会自动消除过载。
- 查明主线程等待的锁及持有者,避免把依赖迁到后台后又立即在主线程等待结果。
- 按依赖组织初始化,区分主线程专属与可并行工作。原文中的 mmkernel、Alpha 是历史架构参考,不是必须接入的标准组件。
系统调度优化
启动时要减少关键路径上的无必要工作:
- 合并重复的同步 Binder 查询,并跟踪 AMS/ATMS、WMS 的锁等待。Binder 调用不等于所有“系统调用”,调用多也不必然意味着都争同一把锁。
- 延后首屏不需要的额外进程;多进程会增加初始化与竞争,但负担不是简单“翻倍”。有隔离要求的进程不能随意合并。
- 留意 Provider、Service 等初始化占用各自进程主线程的时间,尤其是先于
Application.onCreate()的 Provider 初始化;远程 Provider 请求和 Service Binder 方法又可能在 Binder 线程池执行。 - 对可异步的工作安排后台执行,并明确首屏是否依赖其结果。必需且限主线程的工作仍要缩短,不能盲目挪线程。
下面的旧 CPU 图能看到多种工作交错,不能只凭颜色断言 CPU 饱和或某个 App 是唯一原因:
SystemServer 图可见 monitor contention 及锁持有线程,所选窗口为 93.633 ms;这是观察区间,不是所有锁等待之和,也不是整个启动耗时。应顺着持有者继续查:
GC 优化
减少启动路径上的不必要分配,并结合分配量、GC pause 和主线程等待判断收益,不能只数 GC 次数。
- 避免重复生成大字符串、反复序列化和一次性解析首屏不需要的内容。
- 对象复用需要有清晰的所有权和大小上限;对象池可能增加常驻内存或锁竞争。
- Native 分配仍占进程内存,还带来 JNI、生命周期和泄漏风险。不能把“搬到 Native”当成消除内存成本的通用优化。
原案例:支付宝客户端启动速度优化之垃圾回收。
IO 优化
启动中,文件读取、缺页、解压、数据库和其他进程的 I/O 可能相互影响。先记录文件、实际读写字节数、调用次数、线程和持续时间,再区分 CPU 解析与等待;不要用文件总大小代替本次读写量。
首屏必需的网络请求可以异步发起,非必需请求延后;“启动时完全不做网络 I/O”不适用于依赖在线内容的页面。磁盘访问也要尽量移出主线程,并避免主线程随后同步等待。

这张表是原文的观测维度示例:chat.db 文件 500 MB、此次写入 800 KB 是不同字段;表里的 KB/MB 标记未说明十进制还是二进制,不能据此推算精确吞吐率。各行耗时和 Buffer 大小不是推荐配置。


上面两张图分别涉及系统录屏进程和另一个 App,不是同一进程的受控对照。线程状态轨道里的 I/O 等待要看选中状态、阻塞栈和相关事件,不能把橘红色函数片段一概解释成 I/O,也不能只凭局部图证明低内存是根因。
资源重排
原方案通过调整 APK 内资源排列,尝试改善启动读取的局部性,利用 page cache 和预读减少缺页及小块读取。可参考当时的 支付宝安装包重排布案例。
Page cache 缓存文件内容,常规 buffered I/O 和文件映射会用到它;预读是否有效,取决于访问模式与缓存状态。文件内偏移相邻不保证物理存储连续;页大小、文件系统块大小、APK 压缩和映射方式也不能混为一谈。

图上标的是 Linux 4.0(2015)的存储栈,只作历史示意,不代表当前 Android 完整实现。现代构建要考虑 split APK、压缩、对齐和签名;重排必须在构建签名流程内完成并验证产物。缓存已热时收益可能很小,要用相同设备与缓存条件做 A/B,而不是默认“一重排就减少磁盘 I/O”。
类重排
ReDex 的 InterDex 可以根据启动类清单改善 DEX 布局;参见 项目文档。实际还要满足 DEX 容量、主 DEX 约束和后续优化,不能概括成“不分析任何约束,把所有启动类塞进主 dex 即可”,收益也需要同场景 A/B。
新项目可评估 Startup Profiles。 它在构建阶段改善 DEX 中启动代码的局部性;Baseline Profiles 则向 ART 提供关键代码路径用于编译,两者用途不同。按 Startup Profiles 配置文档,DEX layout optimization 从 AGP 8.1 提供、8.3 起默认开启;8.1–8.2 需显式启用,并按文档配置 R8。推荐工具组合为 Macrobenchmark 1.2.0+、AGP 8.2+。生成规则后还要确认 release 产物实际消费,并测试桌面、深链等入口,不套用别家提升百分比。
主页面布局优化
应用主界面布局优化要结合实际 Measure、Layout、Draw 或 Compose 的构建与布局耗时:
- 减少冗余层级和重复测量;层级数量不是唯一性能指标。
- 用 ViewStub 延后暂不需要的 View,但注意首次展开的延迟,不要把卡顿集中到第一次点击。
- 自定义 View 可减少某些叠加成本,同时需要维护交互、无障碍和绘制逻辑;不能保证一定比标准控件快。
闲时调用
IdleHandler 属于 MessageQueue,在所属 Looper 的队列满足空闲条件时执行,不是“某个 Handler 空闲”。返回 true 表示保留以便以后的空闲时机再回调,返回 false 表示移除;true 不表示立即无限循环。
回调仍在这个 Looper 的线程上运行。主队列的 IdleHandler 不适合直接做网络请求、重 I/O 或大量 View 构建;它既不保证何时触发,也不会自动把任务移到后台。可用它轻量安排非必需工作,但不能让首屏必需任务无限等空闲。合同与实现见 IdleHandler 和 Android 10 MessageQueue。
类加载优化
Trace 中的 VerifyClass 可以提示类校验工作,但它的墙钟区间也可能含调度等待;并非每次启动都会重新校验所有方法。要结合实际 ART 版本、编译状态与加载路径分析。

这张带有 dexopt、VERIFY_MODE_NONE 的图是旧运行时示意,不能作为现代 App 关闭 ART 校验的做法。Android 7 起 ART 使用解释、JIT 与 AOT 的组合,具体产物和策略随版本变化,见 ART 配置说明。App 侧优先减少无用初始化,并正确生成、打包和验证 Baseline Profiles;Profile 已打包不等于该次设备启动已经完成预编译。
App 瘦身
包体、安装占用、解码内存和启动耗时是不同指标,要分别看:
- 用 Android Lint / IDE inspections 找无用代码与资源,再确认反射、JNI、动态资源访问等保留规则。
- 在 release 构建中配置 R8 与资源收缩。缩短符号名的混淆与删除无用内容的 shrinking 不是一回事。
RGB_565是每像素 2 字节、无 alpha 的 Bitmap 内存配置,不是替换 PNG/JPEG 的 APK 文件格式。是否适用要看透明度、色彩和解码行为;压缩格式与解码尺寸另行选择。- 资源重命名或减少 DEX 文件数不保证更快。应检查真实包体和启动路径,避免破坏资源查找或为了数量更少而引入额外启动工作。
选择合适的启动框架
先把初始化任务及其依赖画成有向无环图(DAG),再决定阶段、线程和并发上限。图描述的是先后约束,本身既不要求多进程,也不会自动让任务并行或解决拥塞。对必需依赖明确完成/失败状态,不要把“已提交后台任务”当成初始化完成。
下面三张是原手淘案例的阶段划分,包括基础库、页面依赖、可选预加载和按需初始化。m-a、m-f-a、m-b-f、m-idle 是案例自己的标记,不是 Android 生命周期;图里的“一定执行”也不能作为任意 IdleHandler 的保证。



当前可用 Jetpack App Startup 声明 Initializer.dependencies(),将多项自动初始化集中到一个 Provider。它按依赖同步调用 create(),不是自动并发的启动调度器;默认自动初始化通常发生在主线程、Application.onCreate() 之前。若改为手动/懒加载,要检查合并后的 manifest 以及其他 initializer 是否仍依赖它,防止提早初始化或漏初始化。
历史案例:手淘全链路性能优化。
启动网络链路优化
下面整理的是原手淘案例里的问题类别;库名、线程名和耗时来自旧案例,不是所有 App 的默认行为。
问题和优化点
- 发送阶段:某些库初始化或
bindService阻塞请求,图片任务在限流队列中等待。 - 传输阶段:首屏不需要的资源或过大响应占用链路。
- 解析阶段:复杂 JSON、解码或回调长期占用有限工作线程。
- 上屏阶段:结果虽已返回,主线程排队或重回调仍延迟显示。
原文的“解析 3 s、高端机 1 s、低端机 3 s 以上”属于案例描述,缺少可复现实验条件,不能当设备档位的通用阈值。
优化
- 合并重复请求,延后首屏不需要的数据;请求去重不等于盲目把所有网络连接合成一个。
- 限制下载、解析和图片解码并发,防止为了网络快把 CPU、内存或回调队列压满。
- 在合适的工作线程解析,主线程只应用必要结果,并处理取消和过期回调。
- 60 / 90 / 120 Hz 的刷新间隔约为 16.67 / 11.11 / 8.33 ms。一个回调不能独占整个间隔,低于 16 ms 也不保证帧不超时,应按实际帧 deadline 和整体主线程工作判断。
预加载
如果能在用户导航前获知需求,可以提前异步准备数据,让页面就绪后复用结果。要处理取消、错误、账号切换、缓存过期和内存上限;没有提前执行的时间窗口时,只是把工作搬到别处,并不必然缩短端到端等待。
原文的 PreLoader 项目 保留为历史实现参考,接入前应检查维护状态与当前项目兼容性。
保活
进程保留可以省去部分下次启动的工作,但 Activity 已销毁时仍可能是温启动,不能把“进程没死”直接等同于热启动,更不应该以常驻进程替代冷启动优化。
这里说的保活,并不是建议大家用相互唤醒、通知轰炸等手段,而是提供用户需要的功能,合理释放后台资源,停止不必要的服务和动画。
说起来是这个方向,但我也知道,对 App 开发者而言,上面的做法有些理想化:自己已经尽量释放资源,应用到了后台,仍可能被厂商策略处理掉。Android 的生态需要应用开发者和系统厂商一起改善。后台限制、用户设置和厂商策略都有版本差异;厂商白名单属于具体合作安排,不是做好内存优化就能获得的标准承诺。App 仍应能在进程被回收后正确恢复,也不能假定一定收到低内存回调才会被杀。
业务梳理
这里涉及具体业务,每个 App 都不一样,但可以逐项确认启动模块是否必需、依赖谁、可在哪个线程执行。下面仍沿用原案例的四个维度:
- 必要且耗时:先缩小工作量,再把允许离开主线程的部分异步化;首屏依赖的结果必须有明确就绪条件。
- 必要且不耗时:放在合适的初始化阶段,不因“很快”忽略累积成本。
- 非必要但耗时:延后、按需或取消,避免首帧之后所有任务同时爆发。
- 非必要且不耗时:不在启动时执行,需要时再加载;不等于删除仍有业务用途的功能。

图中的分步、异步、延期是三种手段,不是把每个耗时任务搬线程就算完成优化。
业务优化
- 先定位明显瓶颈,减少重复与无用工作,再检查改善是否影响其他入口。
- 结合当前需求偿还技术债,重构范围围绕已证实的启动问题。
原文引用的 业务优化案例 可以作为排查清单,但其中有两点需要纠正:
THREAD_PRIORITY_BACKGROUND = 10是 Android 的线程优先级常量,不是“最多获取 10% CPU 时间片”。CPU 份额受调度组、其他可运行任务和设备策略影响;主线程依赖的关键任务也不宜无判断地降优先级。见 Process 文档。- 多进程 App 的各进程都有自己的 Application 生命周期。应按进程限制具体 SDK/业务初始化,而不是声称系统只在主进程调用
Application.onCreate();子进程自己的必要初始化不能跳过。
其余可迁移的思路是:延后更新与统计等非首屏工作;移除无用旧代码、调试代码、重复逻辑和 SDK Demo 残留;控制线程池总并发;缓存重复查询但定义失效和账号边界。数据库/I/O 移到后台后,还要确认 UI 没有同步等它。
减少Activity的跳转层次
下面保留几种历史窗口切换示意。系统启动窗口是否显示、显示时机和退出过渡受启动类型与系统版本影响;不是点图标就必定立即出现,也不是 AppWindow 对象一创建便完成交接。Android 12+ 应结合 SplashScreen 生命周期理解。
默认 App 的启动窗口流程
1 | StartingWindow(SystemWindow) |
大部分三方 App 启动流程
1 | StartingWindow(SystemWindow) |
糟糕一点的启动流程是这样的
1 | StartingWindow(SystemWindow) |
更糟糕一点的启动流程:去掉了 StartingWindow
1 | SplashActivity(AppWindow) |
减少无意义的 Activity 中转通常有助于缩短路径,但应保留登录、深链和状态恢复所需的路由。图中的“糟糕”是对当时体验的概括,不是禁止一切 SplashActivity 的平台规则。
厂商优化
下面保留系统及厂商优化的分类。除有版本化源码的项目外,其余多为 2019 年的观察线索,具体覆盖范围和当前实现未确认。App 的优化与验收不能依赖某个未公开的厂商策略。
启动加速
系统可以通过调度、性能提示和频率策略帮助启动,但幅度受到温控、电量、竞争负载与厂商实现约束,没有“绝对资源倾斜”的跨设备保证。

图中可见多核频率、频率限制与调度轨道,没有提供所有数值和策略配置,不能只凭密集颜色证明启动 App 独占 CPU、I/O、GPU。厂商资源调度 SDK 也需要具体文档与适用设备,不能把请求提示当成保证拿到大核。
PreFork
Android 10(Q)引入 USAP(Unspecialized App Process)池:预先派生未专门化为某个 App 的进程,符合条件的启动再将其专门化。它不是把已运行过其他 App 的进程反复复用。
Android 10 ZygoteProcess 的默认配置为关闭,实际是否启用取决于设备配置;还要满足参数与启动条件。Android 16 仍检查策略与可用性,USAP 通信失败可回退普通 Zygote 路径。普通 App 不能据此要求所有 Android 10+ 设备必走进程池。
下面保留原采样的进程及内存输出,包括原来的标点。它只能证明这次快照有这些 usap 进程,不能推算固定池大小、每次 fork 耗时或所有设备的内存成本。
1 | 2,348K: usap32 (pid 18731) |
启动消息重排
这是原文记录的厂商方向,没有给出具体公开版本实现。改变启动消息顺序必须保持生命周期、同步屏障和依赖语义;普通 App 不应把任意消息插到队首当成通用加速方案。
主线程、渲染线程加速
厂商可在特定阶段调整调度组、CPU 亲和性或性能提示。主线程/RenderThread 是否跑在大核上要看 Trace 与设备策略,不是所有启动的固定规则;强制迁核也可能带来温控或竞争代价。
启动预测
系统或厂商可能根据历史使用行为预热进程、代码或数据。具体预测策略属于设备实现;预热进程不等于目标 Activity 已存在,下一次也不必然是热启动。测量时把命中预热与未命中的情况区分开。
后台保活
系统会依据进程重要性和资源压力管理后台进程,部分厂商另有白名单或用户设置。保留进程可以减少部分初始化,但不能保证下次热启动,也不能保证一直存活。
后台重启
原文提到的“后台无感重启”属于未注明版本的厂商观察,不能作为 Android 标准启动机制。重启可能暂时释放泄漏内存,却不能修复泄漏或持续崩溃的根因,也不保证用户状态无损或下次热启动。
内存优化
大内存场景可能在启动时触发回收、缺页或资源竞争。系统可回收缓存页,必要时处理低优先级进程,但不是每次内存不足都必须杀掉很多 App。厂商提前回收只是可能的策略;收益要连同其他 App 被回收后重启的代价一起看。
优化启动逻辑
系统更新也可能缩短启动路径。下面是原文保留的 2019 年 ViewRootImpl 修改截图:提交说明为 “Immediately start drawing when becoming visible”,删除新 Surface 场景下推迟绘制的旧逻辑,并提到当时可能带来 5–10 ms 延迟。

这是一个具体系统分支的修复线索,不能推广成“App 减少 doFrame 次数必然加速”,也不能把提交说明里的收益当作当前设备测试结果。
参考文章
- 都9102年了,Android 冷启动优化除了老三样还有哪些新招?
- App startup time
- 历时1年,上百万行代码!首次揭秘手淘全链路性能优化(上)
- 极客时间 : Android 高手开发课
- Facebook-Redex
- 关于 Android 异步启动框架 alpha 的思考
- 支付宝 App 构建优化解析:通过安装包重排布优化 Android 端启动性能
- Redex 官网
- Redex 初探与 Interdex:Andorid 冷启动优化
- Android性能优化笔记(一)——启动优化
本文其他地址
由于博客留言交流不方便,点赞或者交流,可以移步本文的知乎或者掘金页面
关于我 && 博客
下面是个人的介绍和相关的链接,期望与同行的各位多多交流,三人行,则必有我师!
- 博主个人介绍 :里面有个人的微信和微信群链接。
- 本博客内容导航 :个人博客内容的一个导航。
- 个人整理和搜集的优秀博客文章 - Android 性能优化必知必会 :欢迎大家自荐和推荐 (微信私聊即可)
- Android性能优化知识星球:付费社群已于 2026 年停止运营,不再招收新成员;此处保留历史介绍。
一个人可以走的更快 , 一群人可以走的更远
