为什么我们需要关注 OkHttp 中的协程泄漏?

大家好,我是你们这次课程的主讲人。先聊个真实的事——我之前接手过一个项目,线上频繁报内存泄漏,用 LeakCanary 一抓,全是 OkHttp 请求相关的泄漏。当时我挺纳闷的:明明用的是 Retrofit + 协程,代码看着挺干净啊。结果一查线程 dump,发现大量的协程 Job 还挂在后台,Activity 早就销毁了。说白了,协程泄漏就是协程的生命周期比它本该绑定的 Android 组件更长,导致对象无法释放。

那 OkHttp 为什么容易中招呢?因为 OkHttp 本身的 Call 是支持取消的,但协程的 cancel() 如果不主动调用,它就会一直等。加上很多同学习惯用 GlobalScope.launch 或者忘记在 ViewModel 的 onCleared() 里取消 Job,泄漏就成了家常便饭。嗯,这节课我们不聊虚的,就盯着 OkHttp 请求 + 协程 这个组合,把泄漏的根因、排查手段、修复方案讲透。

课程核心目标

你想想看,学完这门课,你能带走什么?我总结了一下,主要有这几点:

目标 具体内容
理解协程泄漏的根因 Scope、Job、CoroutineContext 三者如何导致引用泄漏
掌握 OkHttp 与协程的生命周期绑定 怎么让请求跟着 Activity、Fragment、ViewModel 走
学会使用工具精准排查 LeakCanary、Android Studio Profiler、协程调试插件
实战案例:从泄漏到修复全流程 三个真实线上泄漏代码的解剖与翻新

一句话总结:让每个 OkHttp 请求都“随主组件生,随主组件灭”。

常见协程泄漏场景

我个人习惯在写协程时先把“泄漏场景”在脑海里过一遍。这里的几个典型坑,你大概率也踩过:

  • 未取消的 Job:用 launch 启动协程但不保存 Job,Activity 销毁后协程还在跑。
  • 生命周期绑定错误:把 Dispatchers 和生命周期的 CoroutineScope 混用,比如在 onCreate 里创建了一个 Scope 却忘了在 onDestroy 取消。
  • 滥用 GlobalScope:GlobalScope.launch 里的协程只会被全局的 Application 持有,一跑就是整个 App 的生存期。
  • 匿名内部类/回调持有外引用:OkHttp 的 Callback 里隐式声明了协程,导致外部 Activity 被间接持有。
  • 在 ViewModel 中直接使用 viewModelScope 但用了错误的异步转换:比如用 withContext(Dispatchers.IO) 返回了一个持有 Activity Context 的闭包。

⚠️ 曾经有一个线上问题,用户反馈在快速退出登录再登录后,App 闪退。我查了堆栈,发现是上一次登录的请求协程泄漏了,还在写数据库,导致 IllegalStateException。从这个教训后,我特别在意协程的“自动取消”机制。

知识体系总览

好,我们用一张图把整个排查体系串起来。你看,问题表现、根因、工具、方案、案例,一条线下来,脉络很清晰。

协程泄漏排查知识体系 问题表现 内存增长 | ANR | 异常崩溃 根本原因 Scope 未取消 Job 未取消 | Context 引用泄漏 排查工具 LeakCanary | Android Studio Profiler | MAT 协程调试插件 | Dump Heap 解决方案 结构化并发 | lifecycleScope | viewModelScope SupervisorJob + 异常处理 实践案例 OkHttp + Retrofit + 协程 从泄漏代码到安全重构 提示:每节课都会配套真实的泄漏堆栈和分析过程,动手跟一遍效果最好。

课程适合谁

这门课不是给纯新手准备的。你得有一定的基础:

  • 用过 OkHttp / Retrofit 做过网络请求
  • 知道协程的基本用法,比如 launch、async、withContext
  • 对 Android 组件的生命周期有概念(Activity / Fragment / ViewModel)

如果你满足这三点,那这 30 节课就能帮你从“能跑”升级到“跑得稳、不泄漏”。我个人就是在踩了两次线上泄漏的坑之后,才彻底把协程取消机制刻进 dna 的。你想想看,如果能提前把这些坑堵上,线上事故能少多少?

💡 别担心代码量多,每一章我都会附上完整可运行的 Demo 和泄漏前后的对比。你甚至可以直接把 Demo 里的安全写法复用到自己的项目里。

好,关于课程介绍和目标,我们就聊到这。接下来我们会从第一行代码开始,逐个场景攻克 OkHttp + 协程的泄漏问题。准备好了吗?