根据GlobalScope
我认为我们可以依赖使用全局 CoroutineScope 启动的协程的文档,它总是被执行。文档说:
全局作用域用于启动在整个应用程序生命周期内运行且不会过早取消的顶级协程。
我已经实现了一些测试代码,并且当在存储库中的协程job
内部取消时UserViewModel
继续执行。这是带有我评论的代码:
class UserViewModel(): CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
fun showUser() {
launch {
val repo = Repository()
val userDeferred = repo.getUser()
// if onClean() is called before the coroutine in Repository finishes,
// this line will not be called, but coroutine in Repository will continue executing
val result = userDeferred.await() // wait for result of I/O operation without blocking the main thread
}
}
fun onClean() {
job.cancel()
}
}
class Repository {
fun getUser() = GlobalScope.async {
delay(4000)
// this line is executed no matter whether the job in UserViewModel was canceled or not
"User returned"
}
}
此外,我们可以减少showUser()
功能:
fun showUser() = repo.getUser().then(this) {
// `it` contains the result
// here is the main thread, use `it` to update UI
}
使用扩展功能then
:
fun <T> Deferred<T>.then(scope: CoroutineScope = GlobalScope, uiFun: (T) -> Unit) {
scope.launch { uiFun(this@then.await()) }
}
如果您为 Android 开发并希望确保您的 IO 操作即使在清理 ViewModel 之后也能完全执行,请使用WorkManager。它适用于需要保证即使应用程序退出系统也会运行它们的异步和可延迟任务。