为什么我们需要关注 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。从这个教训后,我特别在意协程的“自动取消”机制。
知识体系总览
好,我们用一张图把整个排查体系串起来。你看,问题表现、根因、工具、方案、案例,一条线下来,脉络很清晰。
课程适合谁
这门课不是给纯新手准备的。你得有一定的基础:
- 用过 OkHttp / Retrofit 做过网络请求
- 知道协程的基本用法,比如
launch、async、withContext - 对 Android 组件的生命周期有概念(Activity / Fragment / ViewModel)
如果你满足这三点,那这 30 节课就能帮你从“能跑”升级到“跑得稳、不泄漏”。我个人就是在踩了两次线上泄漏的坑之后,才彻底把协程取消机制刻进 dna 的。你想想看,如果能提前把这些坑堵上,线上事故能少多少?
好,关于课程介绍和目标,我们就聊到这。接下来我们会从第一行代码开始,逐个场景攻克 OkHttp + 协程的泄漏问题。准备好了吗?