android - 暂停协程直到任务的正确方法已经完成
问题描述
我最近涉足 Kotlin 协程 因为我使用了很多 Google 的库,所以大部分工作都是在Task类中完成的
目前我正在使用这个扩展来暂停协程
suspend fun <T> awaitTask(task: Task<T>): T = suspendCoroutine { continuation ->
task.addOnCompleteListener { task ->
if (task.isSuccessful) {
continuation.resume(task.result)
} else {
continuation.resumeWithException(task.exception!!)
}
}
}
但最近我看到了这样的用法
suspend fun <T> awaitTask(task: Task<T>): T = suspendCoroutine { continuation ->
try {
val result = Tasks.await(task)
continuation.resume(result)
} catch (e: Exception) {
continuation.resumeWithException(e)
}
}
有什么区别,哪一个是正确的?
UPD:第二个示例不起作用,我知道为什么
解决方案
传递给的代码块suspendCoroutine { ... }
不应阻塞正在调用它的线程,从而允许挂起协程。这样,实际线程可以用于其他任务。这是一个关键特性,它允许 Kotlin 协程甚至在单个 UI 线程上扩展和运行多个协程。
第一个示例正确执行,因为它调用task.addOnCompleteListener
(请参阅文档)(它只是添加一个侦听器并立即返回。这就是第一个正常工作的原因。
第二个示例使用Tasks.await(task)
(请参阅文档)阻塞正在调用它的线程并且在任务完成之前不会返回,因此它不允许协程被正确挂起。
推荐阅读
- c# - Directory.GetDirectories 顺序与 Directory.GetFiles 顺序
- mysql - 如何防止json数据输出按字母顺序排序并存储在mysql工作中?
- kotlin - Companion 与 INSTANCE 有何不同
- deep-learning - Pytorch 嵌入层中使用的默认权重初始化是什么?
- javascript - 传单:当缩放相同时删除上一层并添加新的点击层
- postgresql - 意外的数据包类型:Postgres 中抛出 52 - QueryExecutorImpl.processResults
- eclipse - 在 Git 中标记为假定未更改的文件在哪里?
- java - 哪种方法更好地比较方法检查中的值或检查它是否存在于数组中?
- c# - 尝试更新 gridview 中的一行时,会出现以下错误?
- python - 如何合并两个数据框并在其中保留非nan值