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 里初始化了太多东西,首帧渲染的布局层级太深。能异步的丢子线程、能懒加载的等用到再说、布局能扁平化的别嵌套。三点搞好了,启动快个几百毫秒是常事。

相关推荐
传奇开心果编程1 分钟前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程3 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程4 小时前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程5 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程5 小时前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
事圆则缓5 小时前
Android AOSP 定制常见概念:源码目录、系统镜像与刷机流程
android
传奇开心果编程5 小时前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer
supabc1235 小时前
Celium:连接 Windows、Mac、Linux 与 Android,让远程访问和设备管理更简单
android·linux·windows·macos·远程访问·网络管理·celium
Dovis(誓平步青云)6 小时前
导览音频切换太快,旧讲解不能覆盖新展品
android·前端·javascript·ecmascript·音视频·宠物
五彩小白1 天前
自回归和上下文
android