协程,作为现代异步编程的利器,以其简洁的语法和强大的性能,在 Kotlin、Python(asyncio)、Go 等语言中迅速风靡。它让我们可以用近乎同步的方式编写异步代码,极大地简化了并发任务的处理。然而,正如任何强大的工具一样,若使用不当,协程也会带来一系列令人头疼的问题。今天,我们就来深入探讨在协程编程中那些常见的“坑”,并思考如何规避它们。
问题一:协程泄漏
现象: 应用内存持续增长,最终导致 OutOfMemoryError。你可能会发现,即使页面关闭或任务完成,协程仍在后台运行,持有对象无法被垃圾回收。
根源: 协程的生命周期长于其应有的范围。最常见的原因是忘记启动的协程,或者在协程中启动了子协程但未妥善管理。
Kotlin 示例:
class MyViewModel : ViewModel() {
init {
// 错误:在 ViewModel 作用域启动了一个无限循环的协程
viewModelScope.launch {
while (true) {
// 做一些工作...
delay(1000)
}
}
}
}
当这个 ViewModel 被销毁时,viewModelScope 会自动取消其所有子协程。但如果是我们自己创建的 CoroutineScope 而没有在适当的时候调用 cancel(),就会发生泄漏。
解决方案:
- 使用结构化并发: 尽可能在已有的生命周期作用域(如
viewModelScope,lifecycleScope) 中启动协程。 - 持有自定义作用域的引用: 如果创建了自定义的
CoroutineScope,务必在组件销毁时调用scope.cancel()。 - 在协程内部检查
isActive::对于长时间运行的任务,定期检查协程是否仍处于活动状态。
viewModelScope.launch {
while (isActive) {
// 在循环中检查是否被取消
// 做一些工作...
delay(1000)
}
}
问题二:取消与异常处理
现象: 协程无法被及时取消,或者在发生异常时整个应用崩溃,或者异常被静默吞掉。
根源:
- 协作式取消: Kotlin 协程的取消是协作式的。这意味着协程代码必须检查取消信号并主动响应。如果协程正

最低0.47元/天 解锁文章

221

被折叠的 条评论
为什么被折叠?



