首页 > 解决方案 > 在 Kotlin 中将 Callback 转换为可暂停的协程

问题描述

我目前有一个回调,它不是同步返回一个值,而是需要做一些异步工作,然后返回结果。我一直在研究如何做到这一点,但我不清楚。到目前为止,我所取得的成就是这样的,但是由于我需要在 foo 方法中添加一个 return,所以首先它返回“something”,然后返回调用 someMethod() 的结果。

我假装的可能吗?

  class CustomClass() :
    SomeClass.SomeInterface {

    override fun foo(p0: SomeType): String {
      val result = "something"
      MainScope().launch {
        withContext(Dispatchers.IO) {
          result = someMethod()
        }
      }
      return result
    }

    suspend fun someMethod(): String =
      suspendCancellableCoroutine { cancelableContinuation ->
        //TODO: register some listener that will end up calling 
        cancelableContinuation.resume("some_value", {})
      }

提前致谢!

标签: androidkotlinkotlin-coroutines

解决方案


您不能同步返回结果,因此foo必须定义为挂起函数。

此外,没有理由将挂起函数调用包装在withContext. 挂起函数(如果组合正确)在内部包装任何阻塞代码,因此它们可以安全地从任何调度程序调用,因此没有理由指定一个使用withContext

如果你withContext去掉你没有等待的协程的启动,foo()除了调用之外什么都不做,所以你可以把someMethod代码从. 但必须定义为函数。someMethodfoofoosuspend

override suspend fun foo(p0: SomeType): String = suspendCancellableCoroutine { continuation ->
    val request = someApi.request(p0) { result: String ->
        continuation.resume(result)
    }
    continuation.invokeOnCancellation {
        request.cancel()
    }
}

通常,您不希望像这样的模型类从它们自己的 CoroutineScopes 启动协程。只需让他们公开挂起功能即可。由 Activity、Fragment 和 ViewModel 等更高级别的类来从其所需范围启动协程,以便它们可以控制协程生命周期。


推荐阅读