【问题标题】:Correct way to suspend coroutine until Task<T> is complete在 Task<T> 完成之前暂停协程的正确方法
【发布时间】:2018-10-23 06:09:58
【问题描述】:

我最近开始研究 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:第二个示例不起作用,我知道为什么

【问题讨论】:

    标签: android kotlin kotlin-coroutines


    【解决方案1】:

    传递给suspendCoroutine { ... } 的代码块不应阻塞正在调用它的线程,从而允许挂起协程。这样,实际线程可以用于其他任务。这是一个关键特性,它允许 Kotlin 协程扩展并在单个 UI 线程上运行多个协程。

    第一个示例正确执行,因为它调用了task.addOnCompleteListener (see docs)(它只是添加了一个侦听器并立即返回。这就是第一个正常工作的原因。

    第二个示例使用Tasks.await(task) (see docs),它阻塞正在调用它的线程并且在任务完成之前不会返回,因此它不允许协程正确挂起。

    【讨论】:

      猜你喜欢
      • 2012-07-18
      • 2016-11-22
      • 1970-01-01
      • 1970-01-01
      • 2011-02-21
      • 1970-01-01
      • 1970-01-01
      • 2020-12-23
      相关资源
      最近更新 更多