在我看来,Kotlin Coroutines(协程) 大大简化了同步和异步代码。但是,我发现了许多开发者在使用协程时会犯一些通用性的错误。
1. 在使用协程时实例化一个新的 Job 实例
有时候你会需要一个 job
来对协程进行一些操作,例如,稍后取消。另外由于协程构建器 launch{}
和 async{}
都需要 job
作为入参,你可能会想到创建一个新的 job
实例作为参数来使用。这样的话,你就拥有了一个 job
引用,稍后你可以调用它的 .cancel()
方法。
fun main() = runBlocking {
val coroutineJob = Job()
launch(coroutineJob) {
println("performing some work in Coroutine")
delay(100)
}.invokeOnCompletion { throwable ->
if (throwable is CancellationException) {
println("Coroutine was cancelled")
}
}
// cancel job while Coroutine performs work
delay(50)
coroutineJob.cancel()
}
这段代码看起来没有任何问题,协程被成功取消了。
>_
performing some work in Coroutine
Coroutine was cancelled
Process finished with exit code 0
但是,让我们试试在协程作用域 CoroutineScope
中运行这个协程,然后取消协程作用域而不是协程的 job
。
fun main() = runBlocking {
val scopeJob = Job()
val scope = CoroutineScope(scopeJob)
val coroutineJob = Job()
scope.launch(coroutineJob) {
println("performing some work in Coroutine")
delay(100)
}.invokeOnCompletion { throwable ->
if (throwable is CancellationException) {
println("Coroutine was cancelled")
}
}
// cancel scope while Coroutine performs work
delay(50)
scope.cancel()
}
当作用域被取消时,它内部的所有协程都会被取消。但是当我们再次执行修改过的代码时,情况并不是这样。
>_
performing some work in Coroutine
Process finished with exit code 0
现在,协程没有被取消,Coroutine was cancelled
没有被打印。
为什么会这样?
原来,为了让异步/同步代码更加安全,协程提供了革命性的特性 —— “