Kotlin协程上下文安全踩坑记录
最近在开发一个Android应用时,遇到了一个令人头疼的协程上下文安全问题。项目使用了Jetpack组件,包括ViewModel和LiveData,一切都看起来很完美。
问题复现
在ViewModel中定义了一个协程作用域:
class MyViewModel : ViewModel() {
private val viewModelScope = CoroutineScope(Dispatchers.Main)
fun fetchData() {
viewModelScope.launch {
// 模拟网络请求
val data = withContext(Dispatchers.IO) {
fetchFromNetwork()
}
// 更新UI
updateUI(data)
}
}
}
看似正常的代码,但在某些情况下出现了内存泄漏。经过排查发现,当Activity被销毁后,协程仍在后台执行,试图更新已经销毁的UI组件。
根本原因
问题出在我们手动创建了CoroutineScope而没有正确管理其生命周期。虽然使用了Dispatchers.Main,但当ViewModel被回收时,协程并不会自动取消。
解决方案
正确的做法是使用viewModelScope:
class MyViewModel : ViewModel() {
fun fetchData() {
viewModelScope.launch {
val data = withContext(Dispatchers.IO) {
fetchFromNetwork()
}
updateUI(data)
}
}
}
viewModelScope会自动与ViewModel的生命周期绑定,在ViewModel销毁时自动取消所有协程。
重要提醒
- 永远不要手动创建CoroutineScope,除非你明确知道如何管理其生命周期
- 使用Jetpack组件提供的作用域:
viewModelScope、lifecycleScope - 注意Context切换:在IO线程执行耗时操作后,记得切回主线程更新UI
这个坑踩得真是血泪史,希望大家引以为戒!

讨论