1. 泄漏现象识别

Retrofit 回调泄漏并不会像崩溃那样立即暴露,而是通过一系列渐进式性能症状逐渐显现。本节建立一套可观测的“症状‑故障”对应表,帮助你在第一现场锁定可疑的内存问题。

Retrofit 回调泄漏现象故障树 Retrofit 回调泄漏 内存抖动 GC 频繁 OOM LeakCanary 报告 分配率飙升、短时 大量对象创建 / 回收 Logcat 频繁打印 GC_CONCURRENT / AllocTF 应用崩溃 / kill 堆转储文件 > 90% 限制 自动侦测泄漏 生成泄漏链报告

1.1 四种典型现象的现场特征

现象用户可感知表现工具证据优先排查方向
内存抖动 列表滑动卡顿、动画掉帧 Profiler 内存图锯齿状;Allocation Tracking 显示大量临时对象 检查回调内部是否频繁创建匿名内部类或短生命周期对象
GC 频繁 操作响应延迟、应用间歇性无响应 Logcat 中出现 GC_CONCURRENT / GC_FOR_ALLOC 间隔 < 1s 查看 GC 根引用,确认是否有大量 Activity/Fragment 被回调隐性持有
OOM 应用突然退出,或抛出 OutOfMemoryError 堆转储分析显示 Retrofit / OkHttp 相关对象占大量连续空间 抓取 hprof,过滤 Retrofit 回调 + 外层容器实例数
LeakCanary 报告 通知栏提示“泄漏已检测” LeakCanary 自动生成 LeakTrace,指向 Callback → Lifecycle 闭环 直接查看泄漏链中是否出现 Retrofit.Callback 与 Activity / Fragment 的强引用路径

1.2 判断规则:快速定位泄漏概率

使用以下条件式决策表,当多个症状同时出现时,泄漏概率显著升高:

  • 规则 1: 仅内存抖动,无 GC 频繁 → 低概率(临时对象过多,但未形成泄漏)
  • 规则 2: 内存抖动 + GC 频繁 → 中概率(对象未释放,但可能被弱引用 )
  • 规则 3: 内存抖动 + GC 频繁 + 某 Activity 退出后仍有该 Activity 实例 → 高概率(Retrofit 回调持有 Activity 引用)
  • 规则 4: LeakCanary 报告直接确认为泄漏 → 必修复优先级

现场数据采集清单(启动阶段)

一旦发现上述任一现象,立即执行:

  1. 打开 Android Profiler 录制内存 / CPU 片段(持续 30 s 以上)
  2. adb 抓取 logcat 并过滤 GC_* | "LeakCanary"
  3. 通过 adb shell dumpsys meminfo 获取堆摘要
  4. 如已集成 LeakCanary,查看 LeakTrace 中的引用链

1.3 快速验证日志示例

以下 logcat 输出典型地揭示了泄漏早期的 GC 风暴:

2025-03-21 14:23:45.123  I/art  : GC_CONCURRENT freed 4MB, 68% free (8MB/12MB), paused 1.2ms total 15ms
2025-03-21 14:23:45.456  I/art  : GC_FOR_ALLOC freed 1MB, 78% free (7MB/9MB), paused 1ms total 11ms
2025-03-21 14:23:45.789  I/art  : GC_CONCURRENT freed 3MB, 62% free (6MB/10MB), paused 0.9ms total 13ms

如果此类日志在用户操作间隙(如页面切换后 5 秒内)持续出现,且对应 Activity 已 onDestroy 但 Profiler 中仍存在该 Activity 实例,则基本确认 Retrofit 回调泄漏。

✨ 技巧: 使用 adb shell dumpsys meminfo 查看 ViewRootImpl 和 Activity 的计数。正常退出单页面后,相关 Activity 计数应归零,否则就是泄漏的直接证据。