Android 应用启动过程

你点了一下图标,App 是怎么从零跑起来的?从 Launcher 到 Activity.onCreate 的完整启动链路拆解(附启动优化实战)

目录


一、三种启动状态------冷、温、热

App 启动不是只有一种情况。Android 官方把它分三类:

状态 进程是否存在 Activity 是否存在 耗时 场景
冷启动 不存在 不存在 最慢,500ms ~ 2s+ 第一次打开、被系统杀了之后
温启动 存在 不存在 中等,200ms ~ 500ms 按返回键退出后重新打开
热启动 存在 onStop 状态 最快,50ms ~ 200ms 多任务切回来

#mermaid-svg-gawd4kDu4QlplYe4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gawd4kDu4QlplYe4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gawd4kDu4QlplYe4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gawd4kDu4QlplYe4 .error-icon{fill:#552222;}#mermaid-svg-gawd4kDu4QlplYe4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gawd4kDu4QlplYe4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gawd4kDu4QlplYe4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gawd4kDu4QlplYe4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gawd4kDu4QlplYe4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gawd4kDu4QlplYe4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gawd4kDu4QlplYe4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gawd4kDu4QlplYe4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gawd4kDu4QlplYe4 .marker.cross{stroke:#333333;}#mermaid-svg-gawd4kDu4QlplYe4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gawd4kDu4QlplYe4 p{margin:0;}#mermaid-svg-gawd4kDu4QlplYe4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gawd4kDu4QlplYe4 .cluster-label text{fill:#333;}#mermaid-svg-gawd4kDu4QlplYe4 .cluster-label span{color:#333;}#mermaid-svg-gawd4kDu4QlplYe4 .cluster-label span p{background-color:transparent;}#mermaid-svg-gawd4kDu4QlplYe4 .label text,#mermaid-svg-gawd4kDu4QlplYe4 span{fill:#333;color:#333;}#mermaid-svg-gawd4kDu4QlplYe4 .node rect,#mermaid-svg-gawd4kDu4QlplYe4 .node circle,#mermaid-svg-gawd4kDu4QlplYe4 .node ellipse,#mermaid-svg-gawd4kDu4QlplYe4 .node polygon,#mermaid-svg-gawd4kDu4QlplYe4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gawd4kDu4QlplYe4 .rough-node .label text,#mermaid-svg-gawd4kDu4QlplYe4 .node .label text,#mermaid-svg-gawd4kDu4QlplYe4 .image-shape .label,#mermaid-svg-gawd4kDu4QlplYe4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-gawd4kDu4QlplYe4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gawd4kDu4QlplYe4 .rough-node .label,#mermaid-svg-gawd4kDu4QlplYe4 .node .label,#mermaid-svg-gawd4kDu4QlplYe4 .image-shape .label,#mermaid-svg-gawd4kDu4QlplYe4 .icon-shape .label{text-align:center;}#mermaid-svg-gawd4kDu4QlplYe4 .node.clickable{cursor:pointer;}#mermaid-svg-gawd4kDu4QlplYe4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gawd4kDu4QlplYe4 .arrowheadPath{fill:#333333;}#mermaid-svg-gawd4kDu4QlplYe4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gawd4kDu4QlplYe4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gawd4kDu4QlplYe4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gawd4kDu4QlplYe4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gawd4kDu4QlplYe4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gawd4kDu4QlplYe4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gawd4kDu4QlplYe4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gawd4kDu4QlplYe4 .cluster text{fill:#333;}#mermaid-svg-gawd4kDu4QlplYe4 .cluster span{color:#333;}#mermaid-svg-gawd4kDu4QlplYe4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gawd4kDu4QlplYe4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gawd4kDu4QlplYe4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-gawd4kDu4QlplYe4 .icon-shape,#mermaid-svg-gawd4kDu4QlplYe4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gawd4kDu4QlplYe4 .icon-shape p,#mermaid-svg-gawd4kDu4QlplYe4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gawd4kDu4QlplYe4 .icon-shape .label rect,#mermaid-svg-gawd4kDu4QlplYe4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gawd4kDu4QlplYe4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gawd4kDu4QlplYe4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gawd4kDu4QlplYe4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 不存在
存在
不存在
onStop 状态
用户点击图标
App 进程存在?
冷启动

Zygote fork 新进程

Application 初始化

Activity 创建

首帧渲染

500ms ~ 2s+
Activity 内存中存在?
温启动

无需 fork

只创建 Activity

200ms ~ 500ms
热启动

直接 onRestart → onResume

50ms ~ 200ms

冷启动是最慢的,也是优化重点。下面所有内容默认讲冷启动。


二、冷启动五阶段总览

从点图标到界面可见,一共五个阶段:
#mermaid-svg-ah0dF3mnJN1SEwdA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ah0dF3mnJN1SEwdA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ah0dF3mnJN1SEwdA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ah0dF3mnJN1SEwdA .error-icon{fill:#552222;}#mermaid-svg-ah0dF3mnJN1SEwdA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ah0dF3mnJN1SEwdA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ah0dF3mnJN1SEwdA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ah0dF3mnJN1SEwdA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ah0dF3mnJN1SEwdA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ah0dF3mnJN1SEwdA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ah0dF3mnJN1SEwdA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ah0dF3mnJN1SEwdA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ah0dF3mnJN1SEwdA .marker.cross{stroke:#333333;}#mermaid-svg-ah0dF3mnJN1SEwdA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ah0dF3mnJN1SEwdA p{margin:0;}#mermaid-svg-ah0dF3mnJN1SEwdA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ah0dF3mnJN1SEwdA .cluster-label text{fill:#333;}#mermaid-svg-ah0dF3mnJN1SEwdA .cluster-label span{color:#333;}#mermaid-svg-ah0dF3mnJN1SEwdA .cluster-label span p{background-color:transparent;}#mermaid-svg-ah0dF3mnJN1SEwdA .label text,#mermaid-svg-ah0dF3mnJN1SEwdA span{fill:#333;color:#333;}#mermaid-svg-ah0dF3mnJN1SEwdA .node rect,#mermaid-svg-ah0dF3mnJN1SEwdA .node circle,#mermaid-svg-ah0dF3mnJN1SEwdA .node ellipse,#mermaid-svg-ah0dF3mnJN1SEwdA .node polygon,#mermaid-svg-ah0dF3mnJN1SEwdA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ah0dF3mnJN1SEwdA .rough-node .label text,#mermaid-svg-ah0dF3mnJN1SEwdA .node .label text,#mermaid-svg-ah0dF3mnJN1SEwdA .image-shape .label,#mermaid-svg-ah0dF3mnJN1SEwdA .icon-shape .label{text-anchor:middle;}#mermaid-svg-ah0dF3mnJN1SEwdA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ah0dF3mnJN1SEwdA .rough-node .label,#mermaid-svg-ah0dF3mnJN1SEwdA .node .label,#mermaid-svg-ah0dF3mnJN1SEwdA .image-shape .label,#mermaid-svg-ah0dF3mnJN1SEwdA .icon-shape .label{text-align:center;}#mermaid-svg-ah0dF3mnJN1SEwdA .node.clickable{cursor:pointer;}#mermaid-svg-ah0dF3mnJN1SEwdA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ah0dF3mnJN1SEwdA .arrowheadPath{fill:#333333;}#mermaid-svg-ah0dF3mnJN1SEwdA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ah0dF3mnJN1SEwdA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ah0dF3mnJN1SEwdA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ah0dF3mnJN1SEwdA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ah0dF3mnJN1SEwdA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ah0dF3mnJN1SEwdA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ah0dF3mnJN1SEwdA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ah0dF3mnJN1SEwdA .cluster text{fill:#333;}#mermaid-svg-ah0dF3mnJN1SEwdA .cluster span{color:#333;}#mermaid-svg-ah0dF3mnJN1SEwdA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ah0dF3mnJN1SEwdA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ah0dF3mnJN1SEwdA rect.text{fill:none;stroke-width:0;}#mermaid-svg-ah0dF3mnJN1SEwdA .icon-shape,#mermaid-svg-ah0dF3mnJN1SEwdA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ah0dF3mnJN1SEwdA .icon-shape p,#mermaid-svg-ah0dF3mnJN1SEwdA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ah0dF3mnJN1SEwdA .icon-shape .label rect,#mermaid-svg-ah0dF3mnJN1SEwdA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ah0dF3mnJN1SEwdA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ah0dF3mnJN1SEwdA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ah0dF3mnJN1SEwdA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 1. Launcher 通知 AMS

startActivity() 跨进程调用
2. AMS 通知 Zygote fork

Socket 发 fork 命令 + 参数
3. 新进程启动

ActivityThread.main()

主线程 Looper + attach
4. 生命周期回调

Application.onCreate

Activity.onCreate/onStart/onResume
5. 首帧渲染

ViewRootImpl.performTraversals

用户看到界面


三、阶段一:Launcher 通知 AMS

点图标之后,Launcher 做了一件再普通不过的事------调 startActivity

java 复制代码
// Launcher 里(Launcher3 简化逻辑)
Intent intent = getPackageManager().getLaunchIntentForPackage(packageName);
startActivity(intent);

这个调用是跨进程的------Launcher 通过 Binder 把 Intent 发给 SystemServer 进程里的 AMS:
#mermaid-svg-wISJKKIY6NEOYIrf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wISJKKIY6NEOYIrf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wISJKKIY6NEOYIrf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wISJKKIY6NEOYIrf .error-icon{fill:#552222;}#mermaid-svg-wISJKKIY6NEOYIrf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wISJKKIY6NEOYIrf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wISJKKIY6NEOYIrf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wISJKKIY6NEOYIrf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wISJKKIY6NEOYIrf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wISJKKIY6NEOYIrf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wISJKKIY6NEOYIrf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wISJKKIY6NEOYIrf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wISJKKIY6NEOYIrf .marker.cross{stroke:#333333;}#mermaid-svg-wISJKKIY6NEOYIrf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wISJKKIY6NEOYIrf p{margin:0;}#mermaid-svg-wISJKKIY6NEOYIrf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wISJKKIY6NEOYIrf .cluster-label text{fill:#333;}#mermaid-svg-wISJKKIY6NEOYIrf .cluster-label span{color:#333;}#mermaid-svg-wISJKKIY6NEOYIrf .cluster-label span p{background-color:transparent;}#mermaid-svg-wISJKKIY6NEOYIrf .label text,#mermaid-svg-wISJKKIY6NEOYIrf span{fill:#333;color:#333;}#mermaid-svg-wISJKKIY6NEOYIrf .node rect,#mermaid-svg-wISJKKIY6NEOYIrf .node circle,#mermaid-svg-wISJKKIY6NEOYIrf .node ellipse,#mermaid-svg-wISJKKIY6NEOYIrf .node polygon,#mermaid-svg-wISJKKIY6NEOYIrf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wISJKKIY6NEOYIrf .rough-node .label text,#mermaid-svg-wISJKKIY6NEOYIrf .node .label text,#mermaid-svg-wISJKKIY6NEOYIrf .image-shape .label,#mermaid-svg-wISJKKIY6NEOYIrf .icon-shape .label{text-anchor:middle;}#mermaid-svg-wISJKKIY6NEOYIrf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wISJKKIY6NEOYIrf .rough-node .label,#mermaid-svg-wISJKKIY6NEOYIrf .node .label,#mermaid-svg-wISJKKIY6NEOYIrf .image-shape .label,#mermaid-svg-wISJKKIY6NEOYIrf .icon-shape .label{text-align:center;}#mermaid-svg-wISJKKIY6NEOYIrf .node.clickable{cursor:pointer;}#mermaid-svg-wISJKKIY6NEOYIrf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wISJKKIY6NEOYIrf .arrowheadPath{fill:#333333;}#mermaid-svg-wISJKKIY6NEOYIrf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wISJKKIY6NEOYIrf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wISJKKIY6NEOYIrf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wISJKKIY6NEOYIrf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wISJKKIY6NEOYIrf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wISJKKIY6NEOYIrf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wISJKKIY6NEOYIrf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wISJKKIY6NEOYIrf .cluster text{fill:#333;}#mermaid-svg-wISJKKIY6NEOYIrf .cluster span{color:#333;}#mermaid-svg-wISJKKIY6NEOYIrf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wISJKKIY6NEOYIrf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wISJKKIY6NEOYIrf rect.text{fill:none;stroke-width:0;}#mermaid-svg-wISJKKIY6NEOYIrf .icon-shape,#mermaid-svg-wISJKKIY6NEOYIrf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wISJKKIY6NEOYIrf .icon-shape p,#mermaid-svg-wISJKKIY6NEOYIrf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wISJKKIY6NEOYIrf .icon-shape .label rect,#mermaid-svg-wISJKKIY6NEOYIrf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wISJKKIY6NEOYIrf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wISJKKIY6NEOYIrf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wISJKKIY6NEOYIrf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Binder IPC
不存在
存在
Launcher 进程

startActivity()
AMS(SystemServer 进程)
ActivityStarter

解析 Intent / 权限检查
目标 App 进程

存在吗?
★ startProcessAsync()

去 Zygote 那 fork 一个
直接在已有进程

启动 Activity

AMS 端的核心调用链:

复制代码
ActivityManagerService.startActivity()
  → ActivityTaskManagerService.startActivity()
    → ActivityStarter.execute()
      → ActivityStarter.startActivityUnchecked()
        → ActivityStackSupervisor.startSpecificActivity()
          → 发现进程不存在,调 startProcessAsync()

如果进程已经在了(温/热启动),直接跳到阶段四。冷启动需要往下走。


四、阶段二:AMS 让 Zygote fork 新进程

AMS 通过 Zygote Socket(/dev/socket/zygote)发 fork 命令。前文《Android Zygote 启动过程》详细拆解过这个通信机制。
#mermaid-svg-Z3pHVXcEkjm2wcXj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Z3pHVXcEkjm2wcXj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Z3pHVXcEkjm2wcXj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Z3pHVXcEkjm2wcXj .error-icon{fill:#552222;}#mermaid-svg-Z3pHVXcEkjm2wcXj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Z3pHVXcEkjm2wcXj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Z3pHVXcEkjm2wcXj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Z3pHVXcEkjm2wcXj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Z3pHVXcEkjm2wcXj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Z3pHVXcEkjm2wcXj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Z3pHVXcEkjm2wcXj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Z3pHVXcEkjm2wcXj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Z3pHVXcEkjm2wcXj .marker.cross{stroke:#333333;}#mermaid-svg-Z3pHVXcEkjm2wcXj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Z3pHVXcEkjm2wcXj p{margin:0;}#mermaid-svg-Z3pHVXcEkjm2wcXj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Z3pHVXcEkjm2wcXj .cluster-label text{fill:#333;}#mermaid-svg-Z3pHVXcEkjm2wcXj .cluster-label span{color:#333;}#mermaid-svg-Z3pHVXcEkjm2wcXj .cluster-label span p{background-color:transparent;}#mermaid-svg-Z3pHVXcEkjm2wcXj .label text,#mermaid-svg-Z3pHVXcEkjm2wcXj span{fill:#333;color:#333;}#mermaid-svg-Z3pHVXcEkjm2wcXj .node rect,#mermaid-svg-Z3pHVXcEkjm2wcXj .node circle,#mermaid-svg-Z3pHVXcEkjm2wcXj .node ellipse,#mermaid-svg-Z3pHVXcEkjm2wcXj .node polygon,#mermaid-svg-Z3pHVXcEkjm2wcXj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Z3pHVXcEkjm2wcXj .rough-node .label text,#mermaid-svg-Z3pHVXcEkjm2wcXj .node .label text,#mermaid-svg-Z3pHVXcEkjm2wcXj .image-shape .label,#mermaid-svg-Z3pHVXcEkjm2wcXj .icon-shape .label{text-anchor:middle;}#mermaid-svg-Z3pHVXcEkjm2wcXj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Z3pHVXcEkjm2wcXj .rough-node .label,#mermaid-svg-Z3pHVXcEkjm2wcXj .node .label,#mermaid-svg-Z3pHVXcEkjm2wcXj .image-shape .label,#mermaid-svg-Z3pHVXcEkjm2wcXj .icon-shape .label{text-align:center;}#mermaid-svg-Z3pHVXcEkjm2wcXj .node.clickable{cursor:pointer;}#mermaid-svg-Z3pHVXcEkjm2wcXj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Z3pHVXcEkjm2wcXj .arrowheadPath{fill:#333333;}#mermaid-svg-Z3pHVXcEkjm2wcXj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Z3pHVXcEkjm2wcXj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Z3pHVXcEkjm2wcXj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Z3pHVXcEkjm2wcXj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Z3pHVXcEkjm2wcXj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Z3pHVXcEkjm2wcXj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Z3pHVXcEkjm2wcXj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Z3pHVXcEkjm2wcXj .cluster text{fill:#333;}#mermaid-svg-Z3pHVXcEkjm2wcXj .cluster span{color:#333;}#mermaid-svg-Z3pHVXcEkjm2wcXj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Z3pHVXcEkjm2wcXj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Z3pHVXcEkjm2wcXj rect.text{fill:none;stroke-width:0;}#mermaid-svg-Z3pHVXcEkjm2wcXj .icon-shape,#mermaid-svg-Z3pHVXcEkjm2wcXj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Z3pHVXcEkjm2wcXj .icon-shape p,#mermaid-svg-Z3pHVXcEkjm2wcXj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Z3pHVXcEkjm2wcXj .icon-shape .label rect,#mermaid-svg-Z3pHVXcEkjm2wcXj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Z3pHVXcEkjm2wcXj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Z3pHVXcEkjm2wcXj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Z3pHVXcEkjm2wcXj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Zygote(父进程)
新进程(子进程)
AMS.startProcessAsync()
ZygoteProcess.start()
连接 Zygote Socket

/dev/socket/zygote
发送 fork 参数

--nice-name=com.example.app

--setuid=10086

--setgid=10086
Zygote 收到

Zygote.forkAndSpecialize()
fork() 返回值
返回此 PID 给 AMS

继续 accept 等待
★ RuntimeInit.zygoteInit()

→ ActivityThread.main()

AMS 发给 Zygote 的参数:

复制代码
--runtime-args
--setuid=10086
--setgid=10086
--target-sdk-version=34
--nice-name=com.example.app
--seinfo=default:targetSdkVersion=34

这些参数决定了新进程的身份------UID、GID、进程名、SELinux 上下文。Zygote fork 后在子进程里设好这些值,新进程就有了独立的身份。


五、阶段三:ActivityThread.main ------ App 的 Java 入口

新进程从 Zygote fork 出来后,不走平常的 main 函数,而是从 ActivityThread.main() 开始执行。这是 Android App 进程真正的 Java 入口

java 复制代码
// frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    Looper.prepareMainLooper();           // 1. 准备主线程 Looper

    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);       // 2. ★ 通过 Binder 向 AMS 报到

    Looper.loop();                        // 3. 进入消息循环
}

attach() 做的事------向 AMS 报到:
#mermaid-svg-lRQa3huEbCVcMgbh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lRQa3huEbCVcMgbh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lRQa3huEbCVcMgbh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lRQa3huEbCVcMgbh .error-icon{fill:#552222;}#mermaid-svg-lRQa3huEbCVcMgbh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lRQa3huEbCVcMgbh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lRQa3huEbCVcMgbh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lRQa3huEbCVcMgbh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lRQa3huEbCVcMgbh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lRQa3huEbCVcMgbh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lRQa3huEbCVcMgbh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lRQa3huEbCVcMgbh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lRQa3huEbCVcMgbh .marker.cross{stroke:#333333;}#mermaid-svg-lRQa3huEbCVcMgbh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lRQa3huEbCVcMgbh p{margin:0;}#mermaid-svg-lRQa3huEbCVcMgbh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-lRQa3huEbCVcMgbh .cluster-label text{fill:#333;}#mermaid-svg-lRQa3huEbCVcMgbh .cluster-label span{color:#333;}#mermaid-svg-lRQa3huEbCVcMgbh .cluster-label span p{background-color:transparent;}#mermaid-svg-lRQa3huEbCVcMgbh .label text,#mermaid-svg-lRQa3huEbCVcMgbh span{fill:#333;color:#333;}#mermaid-svg-lRQa3huEbCVcMgbh .node rect,#mermaid-svg-lRQa3huEbCVcMgbh .node circle,#mermaid-svg-lRQa3huEbCVcMgbh .node ellipse,#mermaid-svg-lRQa3huEbCVcMgbh .node polygon,#mermaid-svg-lRQa3huEbCVcMgbh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lRQa3huEbCVcMgbh .rough-node .label text,#mermaid-svg-lRQa3huEbCVcMgbh .node .label text,#mermaid-svg-lRQa3huEbCVcMgbh .image-shape .label,#mermaid-svg-lRQa3huEbCVcMgbh .icon-shape .label{text-anchor:middle;}#mermaid-svg-lRQa3huEbCVcMgbh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-lRQa3huEbCVcMgbh .rough-node .label,#mermaid-svg-lRQa3huEbCVcMgbh .node .label,#mermaid-svg-lRQa3huEbCVcMgbh .image-shape .label,#mermaid-svg-lRQa3huEbCVcMgbh .icon-shape .label{text-align:center;}#mermaid-svg-lRQa3huEbCVcMgbh .node.clickable{cursor:pointer;}#mermaid-svg-lRQa3huEbCVcMgbh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-lRQa3huEbCVcMgbh .arrowheadPath{fill:#333333;}#mermaid-svg-lRQa3huEbCVcMgbh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-lRQa3huEbCVcMgbh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-lRQa3huEbCVcMgbh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lRQa3huEbCVcMgbh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lRQa3huEbCVcMgbh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lRQa3huEbCVcMgbh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-lRQa3huEbCVcMgbh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-lRQa3huEbCVcMgbh .cluster text{fill:#333;}#mermaid-svg-lRQa3huEbCVcMgbh .cluster span{color:#333;}#mermaid-svg-lRQa3huEbCVcMgbh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-lRQa3huEbCVcMgbh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lRQa3huEbCVcMgbh rect.text{fill:none;stroke-width:0;}#mermaid-svg-lRQa3huEbCVcMgbh .icon-shape,#mermaid-svg-lRQa3huEbCVcMgbh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lRQa3huEbCVcMgbh .icon-shape p,#mermaid-svg-lRQa3huEbCVcMgbh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-lRQa3huEbCVcMgbh .icon-shape .label rect,#mermaid-svg-lRQa3huEbCVcMgbh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lRQa3huEbCVcMgbh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-lRQa3huEbCVcMgbh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-lRQa3huEbCVcMgbh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ActivityThread.attach()
AMS.attachApplication()

(通过 Binder)
AMS 收到新进程报到

记住它的 ApplicationThread Binder
AMS 给 App 发消息

★ bindApplication

(创建 Application)
AMS 给 App 发消息

★ scheduleLaunchActivity

(启动目标 Activity)

attach 是关键节点------App 进程通过 Binder 告诉 AMS "我起来了,派活吧"。AMS 收到报到后,通过 App 的 ApplicationThread(也是一个 Binder 对象)发了两条消息:先 bindApplication 创建 Application,再启动目标 Activity。


六、阶段四:Application 和 Activity 的生命周期

AMS 发的两条消息在 App 主线程的消息队列里排队执行:

消息 1:bindApplication → 创建 Application

java 复制代码
// ActivityThread.handleBindApplication()
private void handleBindApplication(AppBindData data) {
    // 1. 创建 Application 实例
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);

    // 2. ★ 回调 Application.onCreate()
    //    你的代码在这里跑!
    app.onCreate();

    // 3. 注册 ContentProvider(如果有的话)
    installContentProviders(app, data.providers);
}

消息 2:scheduleLaunchActivity → 创建 Activity

java 复制代码
// ActivityThread.handleLaunchActivity()
public Activity handleLaunchActivity(...) {
    // 1. performLaunchActivity ------ 创建 Activity,调 onCreate
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        // 2. ★ handleResumeActivity ------ 调 onStart / onResume
        handleResumeActivity(...);
    }
    return a;
}

两条消息的执行顺序:
#mermaid-svg-eppnKmzpnss3eOWA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eppnKmzpnss3eOWA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eppnKmzpnss3eOWA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eppnKmzpnss3eOWA .error-icon{fill:#552222;}#mermaid-svg-eppnKmzpnss3eOWA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eppnKmzpnss3eOWA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eppnKmzpnss3eOWA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eppnKmzpnss3eOWA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eppnKmzpnss3eOWA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eppnKmzpnss3eOWA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eppnKmzpnss3eOWA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eppnKmzpnss3eOWA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eppnKmzpnss3eOWA .marker.cross{stroke:#333333;}#mermaid-svg-eppnKmzpnss3eOWA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eppnKmzpnss3eOWA p{margin:0;}#mermaid-svg-eppnKmzpnss3eOWA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eppnKmzpnss3eOWA .cluster-label text{fill:#333;}#mermaid-svg-eppnKmzpnss3eOWA .cluster-label span{color:#333;}#mermaid-svg-eppnKmzpnss3eOWA .cluster-label span p{background-color:transparent;}#mermaid-svg-eppnKmzpnss3eOWA .label text,#mermaid-svg-eppnKmzpnss3eOWA span{fill:#333;color:#333;}#mermaid-svg-eppnKmzpnss3eOWA .node rect,#mermaid-svg-eppnKmzpnss3eOWA .node circle,#mermaid-svg-eppnKmzpnss3eOWA .node ellipse,#mermaid-svg-eppnKmzpnss3eOWA .node polygon,#mermaid-svg-eppnKmzpnss3eOWA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eppnKmzpnss3eOWA .rough-node .label text,#mermaid-svg-eppnKmzpnss3eOWA .node .label text,#mermaid-svg-eppnKmzpnss3eOWA .image-shape .label,#mermaid-svg-eppnKmzpnss3eOWA .icon-shape .label{text-anchor:middle;}#mermaid-svg-eppnKmzpnss3eOWA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-eppnKmzpnss3eOWA .rough-node .label,#mermaid-svg-eppnKmzpnss3eOWA .node .label,#mermaid-svg-eppnKmzpnss3eOWA .image-shape .label,#mermaid-svg-eppnKmzpnss3eOWA .icon-shape .label{text-align:center;}#mermaid-svg-eppnKmzpnss3eOWA .node.clickable{cursor:pointer;}#mermaid-svg-eppnKmzpnss3eOWA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-eppnKmzpnss3eOWA .arrowheadPath{fill:#333333;}#mermaid-svg-eppnKmzpnss3eOWA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eppnKmzpnss3eOWA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eppnKmzpnss3eOWA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eppnKmzpnss3eOWA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eppnKmzpnss3eOWA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eppnKmzpnss3eOWA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-eppnKmzpnss3eOWA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eppnKmzpnss3eOWA .cluster text{fill:#333;}#mermaid-svg-eppnKmzpnss3eOWA .cluster span{color:#333;}#mermaid-svg-eppnKmzpnss3eOWA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eppnKmzpnss3eOWA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eppnKmzpnss3eOWA rect.text{fill:none;stroke-width:0;}#mermaid-svg-eppnKmzpnss3eOWA .icon-shape,#mermaid-svg-eppnKmzpnss3eOWA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eppnKmzpnss3eOWA .icon-shape p,#mermaid-svg-eppnKmzpnss3eOWA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-eppnKmzpnss3eOWA .icon-shape .label rect,#mermaid-svg-eppnKmzpnss3eOWA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eppnKmzpnss3eOWA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eppnKmzpnss3eOWA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eppnKmzpnss3eOWA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} AMS 发 bindApplication
App 主线程

handleBindApplication()

Application.attach()

Application.onCreate()★
AMS 发 scheduleLaunchActivity
performLaunchActivity()

Activity.onCreate()★
handleResumeActivity()

Activity.onStart()

Activity.onResume()★
★ 生命周期结束

进入阶段五:渲染

Application.onCreate 跑完才会跑 Activity.onCreate。所以 Application 里做太多事会直接拖慢 Activity 的显示。


七、阶段五:首帧渲染 ------ 用户真正看到界面

onResume 回调回来不代表用户能看到界面了。真正显示在屏幕上,还需要一次渲染流程:
#mermaid-svg-jpUFIm1dOUNwA338{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jpUFIm1dOUNwA338 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jpUFIm1dOUNwA338 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jpUFIm1dOUNwA338 .error-icon{fill:#552222;}#mermaid-svg-jpUFIm1dOUNwA338 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jpUFIm1dOUNwA338 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jpUFIm1dOUNwA338 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jpUFIm1dOUNwA338 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jpUFIm1dOUNwA338 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jpUFIm1dOUNwA338 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jpUFIm1dOUNwA338 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jpUFIm1dOUNwA338 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jpUFIm1dOUNwA338 .marker.cross{stroke:#333333;}#mermaid-svg-jpUFIm1dOUNwA338 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jpUFIm1dOUNwA338 p{margin:0;}#mermaid-svg-jpUFIm1dOUNwA338 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jpUFIm1dOUNwA338 .cluster-label text{fill:#333;}#mermaid-svg-jpUFIm1dOUNwA338 .cluster-label span{color:#333;}#mermaid-svg-jpUFIm1dOUNwA338 .cluster-label span p{background-color:transparent;}#mermaid-svg-jpUFIm1dOUNwA338 .label text,#mermaid-svg-jpUFIm1dOUNwA338 span{fill:#333;color:#333;}#mermaid-svg-jpUFIm1dOUNwA338 .node rect,#mermaid-svg-jpUFIm1dOUNwA338 .node circle,#mermaid-svg-jpUFIm1dOUNwA338 .node ellipse,#mermaid-svg-jpUFIm1dOUNwA338 .node polygon,#mermaid-svg-jpUFIm1dOUNwA338 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jpUFIm1dOUNwA338 .rough-node .label text,#mermaid-svg-jpUFIm1dOUNwA338 .node .label text,#mermaid-svg-jpUFIm1dOUNwA338 .image-shape .label,#mermaid-svg-jpUFIm1dOUNwA338 .icon-shape .label{text-anchor:middle;}#mermaid-svg-jpUFIm1dOUNwA338 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jpUFIm1dOUNwA338 .rough-node .label,#mermaid-svg-jpUFIm1dOUNwA338 .node .label,#mermaid-svg-jpUFIm1dOUNwA338 .image-shape .label,#mermaid-svg-jpUFIm1dOUNwA338 .icon-shape .label{text-align:center;}#mermaid-svg-jpUFIm1dOUNwA338 .node.clickable{cursor:pointer;}#mermaid-svg-jpUFIm1dOUNwA338 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jpUFIm1dOUNwA338 .arrowheadPath{fill:#333333;}#mermaid-svg-jpUFIm1dOUNwA338 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jpUFIm1dOUNwA338 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jpUFIm1dOUNwA338 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jpUFIm1dOUNwA338 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jpUFIm1dOUNwA338 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jpUFIm1dOUNwA338 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jpUFIm1dOUNwA338 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jpUFIm1dOUNwA338 .cluster text{fill:#333;}#mermaid-svg-jpUFIm1dOUNwA338 .cluster span{color:#333;}#mermaid-svg-jpUFIm1dOUNwA338 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jpUFIm1dOUNwA338 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jpUFIm1dOUNwA338 rect.text{fill:none;stroke-width:0;}#mermaid-svg-jpUFIm1dOUNwA338 .icon-shape,#mermaid-svg-jpUFIm1dOUNwA338 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jpUFIm1dOUNwA338 .icon-shape p,#mermaid-svg-jpUFIm1dOUNwA338 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jpUFIm1dOUNwA338 .icon-shape .label rect,#mermaid-svg-jpUFIm1dOUNwA338 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jpUFIm1dOUNwA338 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jpUFIm1dOUNwA338 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jpUFIm1dOUNwA338 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Activity.onResume()
WindowManager.addView()

创建 ViewRootImpl
ViewRootImpl.requestLayout()
scheduleTraversals()

注册 VSync 信号回调
doTraversal()
★ performMeasure()

测量 View 大小
★ performLayout()

摆放 View 位置
★ performDraw()

绘制到 Surface
SurfaceFlinger 合成

帧送到屏幕
★ 用户看到界面

onResume 到首帧显示之间还有一段距离。布局越复杂、层级越深,这段距离越长。


八、完整时序图

把五个阶段串成一根完整的线:
SurfaceFlinger App ActivityThread Zygote AMS Launcher SurfaceFlinger App ActivityThread Zygote AMS Launcher #mermaid-svg-e5cSDVAKCmVmlpXo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-e5cSDVAKCmVmlpXo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-e5cSDVAKCmVmlpXo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-e5cSDVAKCmVmlpXo .error-icon{fill:#552222;}#mermaid-svg-e5cSDVAKCmVmlpXo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-e5cSDVAKCmVmlpXo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-e5cSDVAKCmVmlpXo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-e5cSDVAKCmVmlpXo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-e5cSDVAKCmVmlpXo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-e5cSDVAKCmVmlpXo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-e5cSDVAKCmVmlpXo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-e5cSDVAKCmVmlpXo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-e5cSDVAKCmVmlpXo .marker.cross{stroke:#333333;}#mermaid-svg-e5cSDVAKCmVmlpXo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-e5cSDVAKCmVmlpXo p{margin:0;}#mermaid-svg-e5cSDVAKCmVmlpXo .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-e5cSDVAKCmVmlpXo text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-e5cSDVAKCmVmlpXo .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-e5cSDVAKCmVmlpXo .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-e5cSDVAKCmVmlpXo .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-e5cSDVAKCmVmlpXo .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-e5cSDVAKCmVmlpXo #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-e5cSDVAKCmVmlpXo .sequenceNumber{fill:white;}#mermaid-svg-e5cSDVAKCmVmlpXo #sequencenumber{fill:#333;}#mermaid-svg-e5cSDVAKCmVmlpXo #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-e5cSDVAKCmVmlpXo .messageText{fill:#333;stroke:none;}#mermaid-svg-e5cSDVAKCmVmlpXo .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-e5cSDVAKCmVmlpXo .labelText,#mermaid-svg-e5cSDVAKCmVmlpXo .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-e5cSDVAKCmVmlpXo .loopText,#mermaid-svg-e5cSDVAKCmVmlpXo .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-e5cSDVAKCmVmlpXo .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-e5cSDVAKCmVmlpXo .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-e5cSDVAKCmVmlpXo .noteText,#mermaid-svg-e5cSDVAKCmVmlpXo .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-e5cSDVAKCmVmlpXo .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-e5cSDVAKCmVmlpXo .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-e5cSDVAKCmVmlpXo .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-e5cSDVAKCmVmlpXo .actorPopupMenu{position:absolute;}#mermaid-svg-e5cSDVAKCmVmlpXo .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-e5cSDVAKCmVmlpXo .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-e5cSDVAKCmVmlpXo .actor-man circle,#mermaid-svg-e5cSDVAKCmVmlpXo line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-e5cSDVAKCmVmlpXo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 1. startActivity() Binder 解析 Intent,权限检查 2. fork 命令 Socket 3. fork 子进程,ActivityThread.main() Looper.prepareMainLooper() 3. attachApplication() Binder,报到 4. bindApplication Binder Application.onCreate() 4. scheduleLaunchActivity Binder Activity.onCreate() → onStart() → onResume() 5. ViewRootImpl.performTraversals 合成,送帧到屏幕 ★ 用户看到界面


九、实战:精准测量冷启动耗时

方法一:用 am start -W(命令行)

bash 复制代码
adb shell am start -W com.example.app/.MainActivity

# 输出:
# Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.app/.MainActivity }
# Status: ok
# Activity: com.example.app/.MainActivity
# ThisTime: 452        ← 最后一个 Activity 的启动耗时
# TotalTime: 786       ← 从 AMS 收到请求到 Activity 启动完成
# WaitTime: 824        ← 从 AMS 收到请求到首帧绘制完成 + 后台等待
  • ThisTime:最后一个 Activity 自身启动耗时,一般比 TotalTime 小
  • TotalTime:从 AMS 开始处理到 Activity 启动完成,包含 Application 创建时间
  • WaitTime:最接近用户体感的时间------从 startActivity 到首帧显示

方法二:用 Android Studio Profiler

Run → Profile app → 选 CPU / Memory → 点击"Capture Startup" → 启动 App → 自动记录启动各阶段时间轴。

方法三:代码打点

java 复制代码
// Application
public class MyApp extends Application {
    public static long APP_START_TIME;

    @Override
    public void onCreate() {
        APP_START_TIME = SystemClock.uptimeMillis();
        super.onCreate();
    }
}

// Activity
public class MainActivity extends AppCompatActivity {
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            long cost = SystemClock.uptimeMillis() - MyApp.APP_START_TIME;
            Log.d("Startup", "冷启动总耗时: " + cost + "ms");
        }
    }
}

onWindowFocusChanged(hasFocus=true) 是首帧渲染完成后的第一个回调,用它算启动耗时最接近用户体感。

方法四:系统日志自动打印

bash 复制代码
adb logcat -b events | grep am_activity_launch_time
# 输出:
# am_activity_launch_time: [0,12345678,com.example.app/.MainActivity,350,200,550]
# ↑ 最后一个数 550 就是 TotalTime

十、实战:启动速度优化

方向一:Application.onCreate 做减法

这是启动优化的头号目标。很多第三方 SDK 在 Application.onCreate 里做初始化------网络、数据库、埋点、图片库......全部挤在一条线上等。

java 复制代码
// ❌ 在 Application.onCreate 里串行初始化所有东西
public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        initNetwork();       // 100ms
        initDatabase();      // 150ms
        initImageLoader();   // 200ms
        initCrashReport();   // 80ms
        initAnalytics();     // 60ms
        // 总共 590ms ------ 太长了
    }
}

// ✓ 能异步的丢子线程、能懒加载的等用到再说
public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        // 必须在主线程且启动时就用的
        initCrashReport();

        // 可以异步的------丢子线程
        new Thread(() -> {
            initAnalytics();
            initNetwork();
        }).start();

        // 用到再初始化的------去掉 onCreate 里的调用
    }

    // 懒加载
    private ImageLoader getImageLoader() {
        if (imageLoader == null) {
            imageLoader = initImageLoader();
        }
        return imageLoader;
    }
}

方向二:Theme 优化------干掉白屏/黑屏

冷启动时 Zygote 在 fork,系统会先显示一个预览窗口(Starting Window),这个窗口的颜色取决于你的 Theme:

xml 复制代码
<!-- ❌ 默认深色主题 → 启动时闪黑屏 -->
<item name="android:windowBackground">@color/black</item>

<!-- ✓ 设成跟启动页一样的背景 → 视觉上"秒开" -->
<style name="AppTheme.Launcher">
    <item name="android:windowBackground">@drawable/brand_bg</item>
    <!-- 如果启动页显示 Logo,把这个背景做成 Logo 占位图 -->
</style>

方向三:布局懒加载 / ViewStub

首页不一定需要一次性把全部 View 都创建出来:

xml 复制代码
<!-- 那些一开始不显示的布局,用 ViewStub 延迟创建 -->
<ViewStub
    android:id="@+id/stub_detail"
    android:layout="@layout/detail_section"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inflatedId="@+id/detail_section" />
java 复制代码
// 在 onResume 之后或者用户操作时才 inflate
viewStub.inflate();

方向四:PreDrawListener 延迟非关键操作

java 复制代码
// 在首帧绘制完成后再执行非关键初始化
ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content), (v, insets) -> {
    // 此时首帧已经渲染
    initNonCriticalStuff();
    return insets;
});

优化效果对比:

优化项 优化前 优化后 省了多少
Application.onCreate 异步 590ms 180ms -410ms
Theme 去白屏 白屏 ~200ms 0(视觉秒开) -200ms 感知
布局 ViewStub 创建 40 个 View 创建 12 个 View -80ms
合计 ~870ms ~260ms + 视觉秒开 省了 600ms

十一、启动优化中 Application 的坑

坑 1:ContentProvider 默认在主线程 onCreate

Application 里声明的 ContentProvider 会在 Application.onCreate 之前被执行(主线程),这又多了一个启动耗时的来源。

java 复制代码
// 你的 ContentProvider ------ 在 Application.onCreate 之前跑!
public class InitProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        // ★ 这里在主线程跑,而且是 Application 创建之前
        initSomething();  // 如果这里耗时,启动直接慢了
        return false;
    }
}

你用的一些第三方 SDK 可能就是用 ContentProvider 来初始化的------Google Firebase、LeakCanary 都是这么干的。检查一下你的 AndroidManifest:

bash 复制代码
adb shell dumpsys package <your_package> | grep -A 5 "ContentProvider"

坑 2:Application.onCreate 调到了 Activity 里的东西

Application 创建时 Activity 还没影。如果在 Application.onCreate 里调任何跟 Activity 相关的方法,直接崩溃。


十二、常见踩坑记录

坑 1:用 System.currentTimeMillis 打点不准

java 复制代码
// ❌ 用墙钟(受用户改时间影响)
long start = System.currentTimeMillis();

// ✓ 用 uptimeMillis(系统启动后的时间,单调递增)
long start = SystemClock.uptimeMillis();

坑 2:onResume 里做耗时操作导致 ANR

onResume 受 Input 事件限制------5 秒内没返回就 ANR。不要在 onResume 里做 IO 或复杂计算。

坑 3:启动页跳转到主页时没有 finish

java 复制代码
// ❌ 启动页调 startActivity 后没 finish
startActivity(new Intent(this, MainActivity.class));
// 用户在 MainActivity 按返回键,又回到启动页------体验很差

// ✓ 启动页 finish 自己
startActivity(new Intent(this, MainActivity.class));
finish();

坑 4:am start -W 测出来的时间跟用户体感不一样

am start -W 的 TotalTime 是从 AMS 收到请求算起。用户体感是从点图标算起。加上 Launcher → AMS 的 Binder 调用 + Input 分发延迟,用户体感会多出 总量 ~100ms。

坑 5:以为多重几层布局不影响

一个 RelativeLayout 嵌套两层 LinearLayout,整个层级树多出几十个 measure/layout 调用。冷启动阶段 View 树本来就要全量遍历,层级越深耗时成倍增长:

bash 复制代码
# 用 systrace 看 View 渲染耗时
python systrace.py -a com.example.app gfx view

# 或者 Android Studio Layout Inspector
# 看 View 树深度------超过 7 层就该扁平化了

十三、总结

冷启动五阶段速记:
#mermaid-svg-tTvTrcd2saJa6uLV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tTvTrcd2saJa6uLV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tTvTrcd2saJa6uLV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tTvTrcd2saJa6uLV .error-icon{fill:#552222;}#mermaid-svg-tTvTrcd2saJa6uLV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tTvTrcd2saJa6uLV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tTvTrcd2saJa6uLV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tTvTrcd2saJa6uLV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tTvTrcd2saJa6uLV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tTvTrcd2saJa6uLV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tTvTrcd2saJa6uLV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tTvTrcd2saJa6uLV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tTvTrcd2saJa6uLV .marker.cross{stroke:#333333;}#mermaid-svg-tTvTrcd2saJa6uLV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tTvTrcd2saJa6uLV p{margin:0;}#mermaid-svg-tTvTrcd2saJa6uLV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-tTvTrcd2saJa6uLV .cluster-label text{fill:#333;}#mermaid-svg-tTvTrcd2saJa6uLV .cluster-label span{color:#333;}#mermaid-svg-tTvTrcd2saJa6uLV .cluster-label span p{background-color:transparent;}#mermaid-svg-tTvTrcd2saJa6uLV .label text,#mermaid-svg-tTvTrcd2saJa6uLV span{fill:#333;color:#333;}#mermaid-svg-tTvTrcd2saJa6uLV .node rect,#mermaid-svg-tTvTrcd2saJa6uLV .node circle,#mermaid-svg-tTvTrcd2saJa6uLV .node ellipse,#mermaid-svg-tTvTrcd2saJa6uLV .node polygon,#mermaid-svg-tTvTrcd2saJa6uLV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tTvTrcd2saJa6uLV .rough-node .label text,#mermaid-svg-tTvTrcd2saJa6uLV .node .label text,#mermaid-svg-tTvTrcd2saJa6uLV .image-shape .label,#mermaid-svg-tTvTrcd2saJa6uLV .icon-shape .label{text-anchor:middle;}#mermaid-svg-tTvTrcd2saJa6uLV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tTvTrcd2saJa6uLV .rough-node .label,#mermaid-svg-tTvTrcd2saJa6uLV .node .label,#mermaid-svg-tTvTrcd2saJa6uLV .image-shape .label,#mermaid-svg-tTvTrcd2saJa6uLV .icon-shape .label{text-align:center;}#mermaid-svg-tTvTrcd2saJa6uLV .node.clickable{cursor:pointer;}#mermaid-svg-tTvTrcd2saJa6uLV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tTvTrcd2saJa6uLV .arrowheadPath{fill:#333333;}#mermaid-svg-tTvTrcd2saJa6uLV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tTvTrcd2saJa6uLV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tTvTrcd2saJa6uLV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tTvTrcd2saJa6uLV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tTvTrcd2saJa6uLV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tTvTrcd2saJa6uLV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tTvTrcd2saJa6uLV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tTvTrcd2saJa6uLV .cluster text{fill:#333;}#mermaid-svg-tTvTrcd2saJa6uLV .cluster span{color:#333;}#mermaid-svg-tTvTrcd2saJa6uLV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tTvTrcd2saJa6uLV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tTvTrcd2saJa6uLV rect.text{fill:none;stroke-width:0;}#mermaid-svg-tTvTrcd2saJa6uLV .icon-shape,#mermaid-svg-tTvTrcd2saJa6uLV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tTvTrcd2saJa6uLV .icon-shape p,#mermaid-svg-tTvTrcd2saJa6uLV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tTvTrcd2saJa6uLV .icon-shape .label rect,#mermaid-svg-tTvTrcd2saJa6uLV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tTvTrcd2saJa6uLV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tTvTrcd2saJa6uLV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tTvTrcd2saJa6uLV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 点击图标

Launcher → AMS
AMS → Zygote

fork 新进程
ActivityThread.main

Looper + attach
Application.onCreate

Activity.onCreate → onResume
performTraversals

★ 首帧可见

各阶段耗时和优化方向:

阶段 耗时 优化什么
Launcher → AMS ~20ms 基本不用管
AMS → Zygote fork ~50ms 基本不用管
ActivityThread → attach ~100ms 基本不用管
Application.onCreate 100ms ~ 500ms+ 异步 + 懒加载 + 砍 SDK 初始化
Activity.onCreate 100ms ~ 500ms+ 减布局层级 + ViewStub
首帧渲染 50ms ~ 300ms+ 扁平化布局 + Theme 优化
总计 ~420ms ~ 1.7s+

三个关键源码位置:

文件 位置
ActivityThread.main() frameworks/base/core/java/android/app/ActivityThread.java
AMS.startProcessAsync frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
ZygoteProcess.start frameworks/base/core/java/android/os/ZygoteProcess.java

一句话总结: 冷启动慢,基本就慢在两个地方------Application.onCreate 里初始化了太多东西,首帧渲染的布局层级太深。能异步的丢子线程、能懒加载的等用到再说、布局能扁平化的别嵌套。三点搞好了,启动快个几百毫秒是常事。

相关推荐
bqliang1 小时前
译 · Jake Wharton 访谈:Android 圈最熟悉的那个名字
android·程序员·开源
三少爷的鞋1 小时前
Android Data 层 Flow 最佳实践:以冷流为基础,按需转热,避免过早共享状态
android
私人珍藏库9 小时前
【Android】Soul v5.86.0 内置模块版
android·app·工具·软件·多功能
千里马学框架10 小时前
aosp新增窗口层级 Type 完整实现方案(有源码)-wms需求和面试题
android·智能手机·架构·wms·aaos·车机
峥嵘life16 小时前
Android 蓝牙设备连接广播详解-2026
android·python·学习
MusingByte18 小时前
别再裸用 Claude Code 了!安卓开发者必装 13 个官方推荐插件,效率翻 3 倍省 70% token
android
_李小白18 小时前
【android opencv学习笔记】Day 29: 滤波算法之Sobel 边缘检测
android·opencv·学习
Dxy123931021619 小时前
Python 操作 MySQL 事务:从入门到避坑
android·python·mysql
峥嵘life21 小时前
Android getprop 属性限制详解:User 版本属性获取问题分析
android·开发语言·python·学习