综合实战二:用 Profiler 给项目“体检”——性能优化与报告生成

好,咱们接着来。上一章我们把综合实战一的项目跑起来了,功能也通了。但说实话,能跑和跑得好,那是两码事。我见过太多应用,功能没问题,一上线就被用户骂卡顿、耗电、闪退。为什么?因为没做性能分析。

这一章,我就带你用 Android Studio 自带的 Profiler,给咱们的项目做个全面体检。说白了,就是看看内存有没有泄漏、CPU 有没有空转、网络请求是不是合理。然后,咱们再把这些数据整理成一份报告,方便团队 review 或者归档。

为什么非要用 Profiler?

你可能会想:“我 Log 打得好好的,为啥还要用 Profiler?” 嗯,这个问题我刚开始也有。后来有一次,我排查一个内存泄漏,Log 打了三天没找到根因,用 Profiler 一看,一个匿名内部类持有了 Activity 引用,三分钟就定位了。从那以后,我再也不敢小看它。

Profiler 能实时看到:

  • CPU:哪些方法在吃性能,是不是有线程在空转
  • 内存:对象有没有被正确回收,有没有泄漏
  • 网络:请求频率、数据量、响应时间
  • 能耗:哪些操作在疯狂耗电

说白了,它就是你的“应用听诊器”。

Profiler 界面速览

打开 Android Studio,底部工具栏找到 Profiler 标签。点击后选择你的设备和进程。你会看到四条时间线:

区域 作用 我常用的技巧
CPU 查看方法调用耗时、线程状态 用“Call Chart”视图,一眼看出哪个方法最慢
Memory 查看堆内存、对象分配、GC 事件 手动触发 GC,看对象是否被释放
Network 查看请求详情、响应体大小 关注“连接时间”,经常是 DNS 解析慢
Energy 查看耗电事件 定位频繁唤醒锁的问题
我的习惯: 每次性能优化前,先录一段完整的操作流程(比如从首页到详情页再返回),然后回放 Profiler 记录。这样能复现问题,也方便对比优化前后的差异。

第一步:分析 CPU 性能

咱们先看 CPU。点击 CPU 区域,选择“Record & Profile”。然后操作你的应用,比如快速滑动列表、点击按钮。录制个 10 秒就够了。

录制结束后,你会看到火焰图(Flame Chart)和调用树(Call Tree)。我个人更爱用火焰图,因为它直观——越宽的条,说明这个方法占用的 CPU 时间越长。

举个例子,我在综合实战一项目里发现,ImageLoader.loadImage() 这个方法占了 30% 的 CPU 时间。嗯,这不对劲。点进去一看,原来每次加载图片都做了全尺寸解码,没有缩略图处理。

优化方案: 使用 Glide 或 Coil 这类图片加载库,它们自带内存缓存和缩略图支持。别自己写图片加载,坑太多。

第二步:揪出内存泄漏

内存泄漏是 Android 开发的“老朋友”了。怎么用 Profiler 找?很简单:

  1. 进入 Memory 面板,点击“Dump Java Heap”
  2. 等待几秒,生成堆转储文件
  3. 在“Class List”视图里,按“Retained Size”排序
  4. 找那些不该存在的对象,比如已经关闭的 Activity

我曾经在一个项目里,发现 MainActivity 的实例数一直在涨,退出页面也不减少。点进去一看,是一个静态的 Handler 持有了 Activity 的引用。修复方法很简单:用 static 内部类 + WeakReference

注意: 不要只看“Shallow Size”,那是对象本身的大小。要看“Retained Size”,它包含了这个对象持有的所有子对象的大小。这才是真正的泄漏影响。

第三步:网络请求优化

网络面板能告诉你每个请求的耗时、数据量、状态码。我一般关注两点:

  • 请求频率:是不是在短时间内重复请求了相同接口?
  • 响应体大小:是不是返回了太多不需要的字段?

在综合实战一里,我发现首页的列表接口每次返回 200 条数据,但用户只看了前 10 条。这就是浪费。优化方案:后端加个分页参数,前端用 Paging 3 库做分页加载。

小技巧: 在 Profiler 的网络面板里,可以直接查看请求和响应的 Header 和 Body。有时候你会发现,某个请求的 Cookie 过期了,导致一直重定向。这种问题 Log 很难看出来,但 Profiler 一目了然。

第四步:生成性能报告

优化完了,怎么证明你做了工作?生成一份报告。Android Studio 支持导出 Profiler 数据为 .perf 文件,但说实话,那个格式不太友好。我建议你这样做:

  1. 在 Profiler 里,点击“Export”按钮,选择“Export as HTML”
  2. 或者,手动截图 + 写文档,把关键数据贴进去
  3. 报告里要包含:优化前后的对比数据、修改的代码片段、结论

举个例子,我的报告里会这样写:

优化前:列表滑动卡顿,CPU 占用 45%,GC 频繁
优化后:列表滑动流畅,CPU 占用 12%,GC 次数减少 80%

修改内容:
1. 图片加载改用 Glide,添加缩略图
2. 列表数据改用 DiffUtil,减少不必要的刷新
3. 网络请求添加缓存策略

这份报告,你发给 leader 看,或者放到项目文档里,都很有说服力。

核心逻辑流程图

下面这张图,概括了咱们这一章的核心流程。从 Profiler 启动,到分析 CPU、内存、网络,最后生成报告。你可以把它当作一个检查清单。

Profiler 性能分析核心流程 启动 Profiler 选择分析维度:CPU / 内存 / 网络 CPU 分析 火焰图 / 调用树 内存分析 堆转储 / 泄漏检测 网络分析 请求耗时 / 数据量 定位问题 → 优化代码 生成性能报告

避坑指南

最后,分享几个我踩过的坑:

  • 不要在生产环境开 Profiler:Profiler 本身会消耗性能,数据会失真。我都是在 debug 包上分析。
  • 别忘了清理缓存:每次分析前,先清一下应用数据。否则之前的数据会影响结果。
  • 多录几次:单次录制可能有偶然性。我一般录三次,取平均值。
  • 关注“异常峰值”:如果某个时间点 CPU 突然飙到 90%,那大概率是出了 bug。点进去看那个时间点的调用栈。

好了,这一章的内容就到这。拿起你的综合实战一项目,打开 Profiler,动手试试吧。你会发现,性能优化其实没那么玄乎,关键是要用对工具。


公众号:蓝海资料掘金营,微信 deep3321