启动监控三板斧:DisplayManager、adb 与 Play Console
做启动优化,最怕的就是“凭感觉”。你改了几行代码,觉得快了,但到底快了多少?哪个阶段拖了后腿?没有数据支撑,一切优化都是盲人摸象。
这一章,我带你熟悉三套最常用的启动监控工具。它们各有侧重,结合起来基本能覆盖从开发到线上全链路。我自己做项目时,这三样东西几乎天天都要摸一遍——嗯,就像医生手里的听诊器、血压计和CT机。
1. DisplayManager 启动信息:官方最精确的系统级指标
先聊 DisplayManager。说实话,很多人不知道这个 API。它藏在 android.view.Display 里,专门记录系统第一次绘制到屏幕的时间点。
怎么用? 在 Activity 的 onCreate 或 onResume 里加上几行代码:
// 获取 Display 对象
Display display = getWindowManager().getDefaultDisplay();
// 注册启动时间监听(API 24+)
display.getMetrics(new DisplayMetrics());
// 更直接的方式:使用 reportFullyDrawn()
// 在关键内容渲染完成后调用
Activity.reportFullyDrawn();
我的一点经验:reportFullyDrawn() 这个方法非常实用。它告诉系统“我的核心界面已经完整展示了”。系统会在 Logcat 里打出一条包含启动耗时的日志,格式类似:
Displayed com.example.app/.MainActivity: +1s234ms
你可以把它作为冷启动耗时的一个基准。我在多个项目中用这个指标和 adb 命令交叉验证,两者基本吻合。
DisplayManager 信息的主要价值:
- 最接近用户感知:它记录的是屏幕真正亮起的时间,不是代码逻辑跑完的时间。
- 区分冷/温/热启动:系统日志会自动标注。
- 零性能开销:纯系统级统计,不需要额外埋点。
注意:reportFullyDrawn() 只在 Android 4.4(API 19)以上有效。另外,如果你在 Activity 的 onCreate 里做了大量同步耗时任务,DisplayManager 不会等你做完才打时间戳,它只管第一帧的显示。所以——不要让它背锅,你需要结合其他工具看内部耗时。
2. adb shell am start -W:命令行硬核诊断
这是我最常用的调试手段。没有之一。你想想看,在开发机上敲一条命令,一秒后就能看到启动耗时,多爽。
基本命令:
adb shell am start -W -n com.example.app/.MainActivity
输出结果大致如下:
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.app/.MainActivity }
Status: ok
LaunchState: COLD
Activity: com.example.app/.MainActivity
TotalTime: 1234
WaitTime: 1245
Complete
关键字段解释:
| 字段 | 含义 | 个人使用心得 |
|---|---|---|
TotalTime |
从启动到 Activity 完成 onResume() 的耗时 |
我最关注的指标,单位毫秒 |
WaitTime |
包含系统调度、AMS 处理等时间 | 通常比 TotalTime 大一些,但不建议用做优化目标 |
LaunchState |
COLD / WARM / HOT | 必须关注。同一台设备冷启动 1.5s,热启动可能只有 200ms |
批量测试脚本:我自己写过一个自动脚本,每次 CI 构建后,自动在 5 台真机上跑 10 次冷启动,取中位数和 P90。脚本大致逻辑:
# 先强杀进程确保冷启动
adb shell am force-stop com.example.app
sleep 2
adb shell am start -W -n com.example.app/.MainActivity 2>&1 | grep TotalTime
然后把结果写到 CSV 文件里,方便看趋势。这种方法比 Android Studio 的 Profiler 更轻量,适合集成到自动化流程。
我曾经踩过的坑:直接拿 am start -W 的结果和线上数据对比,发现永远对不上。后来搞清楚了——adb 测试时设备是空闲的,而线上用户手机后台跑着微信、抖音,CPU 负载不同。所以 adb 数值用于相对比较(优化前 vs 优化后),不要当成值。
3. Google Play Console 启动报告:线上的真实世界
开发环境再完美,也模拟不出线上用户的百机千态。Google Play Console 里的 Android Vitals 面板,才是真正反映用户体感的起点。
哪里看?
- 登录 Google Play Console → 选择应用 → Android Vitals → 启动时间。
- 会看到 “启动延时(冷启动)”、“启动延时(温启动)”、“启动延时(热启动)” 三个维度。
- 数据按设备型号、Android 版本、内存大小等维度聚合展示。
重点关注两个指标:
- P50 和 P95:P50 代表一半用户的体验,P95 代表最差那 5% 用户的体验。如果 P95 远高于 P50,说明存在某些设备或机型上启动异常慢。
- “差”的占比:Google 定义超过 5 秒的冷启动为“差”。如果你的应用这个比例超过 2%,建议马上排查。
重要提示:Play Console 的启动数据是基于 reportFullyDrawn() 上报的。如果你的应用没有调用 reportFullyDrawn(),那这个面板就是空的!我见过不少团队把代码都优化完了,才发现数据没上报,白忙活一场。
另外,Play Console 还有一些隐藏功能:
- 按地区筛选:不同国家的网络条件会影响启动时下载的资源。
- 查看启动崩溃关联:启动时间过长的 App 往往也伴随 ANR 率高。
- 设置告警阈值:当 P95 启动时间超过某个值(比如 3 秒),自动发邮件提醒。
三者如何配合使用?
我个人习惯的开发流程是这样:
- 日常开发:用
adb shell am start -W快速验证每次改动的效果。改一点测一点,避免积重难返。 - 回归测试:结合 DisplayManager 日志和自动化脚本,在 10 台以上设备跑批量测试,记录
TotalTime和Displayed时间。 - 线上监控:登陆 Play Console 看趋势。如果发现某个版本启动时间突然恶化,立刻定位优化。
嗯,这一套组合拳下来,基本不会有遗漏。记住一个原则:不经过数据验证的优化,都是自我感动。
核心总结:
reportFullyDrawn()+ DisplayManager 日志 = 系统级基准adb shell am start -W= 强插桩,适合本地快速验证- Play Console Android Vitals = 线上用户真实体验数据
- 三者数据互为补充,不要只看一个维度下结论