Android 启动速度与卡顿排查
Android 启动速度与卡顿排查
摘要:启动慢和滚动卡顿通常是主线程承担了过多工作,而不是缺少某个“神奇优化开关”。本文从定义指标、定位耗时、异步初始化到列表与渲染优化,介绍一套可重复的性能排查方法。
一、先定义用户感受到的性能
启动优化先区分冷启动、温启动和热启动。冷启动需要创建进程并初始化应用;温启动复用进程但可能重建 Activity;热启动通常只是把已有界面带回前台。比较数据时要保持场景一致。
滚动性能可以关注帧时间分布和慢帧比例;启动可关注首帧时间及关键内容何时可交互。平均值会掩盖长尾,建议观察中位数和高分位数据,并把设备型号、系统版本和网络条件一并记录。
二、把启动链路拆开
典型启动过程包含进程创建、Application 初始化、首个 Activity 创建、布局和绘制。应用代码能直接控制的部分包括:
- Application 中的同步初始化。
- 主线程上的磁盘、数据库和加密操作。
- 首屏布局复杂度及首帧前的额外工作。
- 首屏图片解码、字体加载和大对象创建。
不要一开始就重写启动流程。先用系统跟踪工具或基准测试采集时间线,确定耗时区段,再对照代码确认调用栈。
三、缩小首帧前的工作量
Application 的 onCreate 只应保留首屏真正需要的初始化。日志 SDK、非首屏数据库预热和推荐内容加载可以推迟到对应能力首次使用时。把代码搬到后台线程本身并不够:如果首屏同步等待后台结果,用户仍然要等待。
可以按依赖分组初始化:首屏必须项尽早完成;可延迟项在首屏展示后执行;只在某功能打开时才需要的能力,延迟到功能入口再创建。延迟工作要有明确触发点和失败处理,避免变成永远没有执行的初始化。
四、减少主线程阻塞
主线程负责处理输入与提交界面更新。文件读写、数据库查询和复杂计算应放到适合的调度器或 Repository 中;结果再回到主线程更新状态。不要在 onDraw、Composable 求值或滚动回调中做解析、排序、大量分配等工作。
布局复杂时,检查深层嵌套、重复测量和一次创建过多子项。长列表使用惰性容器,稳定列表项身份,并提供合适的内容类型帮助容器复用。
五、关注图片与内存
大图解码尺寸远超显示尺寸时,会增加内存与解码耗时。按显示区域请求合适尺寸,避免主线程解码。列表滚动时控制同时加载任务数量,页面离开后取消已不需要的任务。
内存紧张会触发频繁垃圾回收,导致掉帧。性能排查时观察堆分配、位图占用和对象保留路径;避免每帧创建临时集合、格式化字符串或绘制对象。缓存需要限制容量,并有清理策略。
六、用正确的指标验证优化
优化前后应使用相同构建类型、设备、数据量和操作路径。性能基准需要多次测量,关注分布而不是单次最好成绩。启动基准还应区分首次运行、缓存已热和后台进程状态。
宏基准可测量真实应用流程,微基准适合隔离单个函数或算法。基准测试用于重复比较,不代替真实用户设备上的观测。发布后仍要观察崩溃、卡顿和启动数据,发现回归后关联到版本和设备分组。
七、常见误区
- 不要把所有初始化都并发启动;它们可能争抢磁盘和 CPU。
- 不要只看模拟器数据;设备性能和后台策略差异很大。
- 不要为小幅理论收益引入复杂缓存,先测量再判断。
- 不要用延迟展示空白来伪造更快的首帧;首屏关键内容也要纳入指标。
- 基准构建与正式构建的优化设置不同,比较时需保持一致。
八、总结
性能问题需要沿着真实时间线查找。先定义启动或卡顿场景,采集调用与帧数据,再减少首帧前的同步工作、避免主线程重计算、控制图片与内存开销,最后在一致条件下复测。可重复的数据比主观体感更能指导优化。
- 点赞
- 收藏
- 关注作者
评论(0)