如何将 Kotlin 协程与 onSuccessListner 一起使用?

How to use Kotlin Coroutines with an onSuccessListner?

Android Kotlin 中的应用程序开发

我有两个函数F1和F2,它们的结构基本相同。我希望他们 return 一个字符串。 我想像这样使用它们:

// In some other function, say F3

GlobalScope.launch(Dispatchers.Main){

    val result1: Deferred<String> = async(Dispatchers.Main) { F1(img) }
    val result2: Deferred<String> = async(Dispatchers.Main) { F2(img) }

    doSomething(result1.await(), result2.await())
}



// funcion F1:

suspend fun F1(img: Bitmap): Deferred<String>{
    obj.process(img)
        .addOnSuccessListner{ result ->
            // result is the string to be returned as Deferred
        }
}

// function F2, same structure as F1

suspend fun F2(img: Bitmap): Deferred<String>{
    obj.process(img)
        .addOnSuccessListner{ result ->
            // result is the string to be returned as Deferred
        }
}


我想 运行 使用 Kotlin 协程并行执行 F1 和 F2,但目前我对如何重构 F1 和 F2 以使 F3 代码正常工作感到困惑。希望能提供一些帮助。

我相信 suspendCoroutine 就是您要找的。 例如,在您的情况下:

suspend fun F1(img: Bitmap) = suspendCoroutine<String> {
    obj.process(img)
        .addOnSuccessListner{ result ->
            it.resume(result)
        }
} 

您可能还需要 suspendCancellableCoroutine

您使用 Deferred 的次数太多了:既作为 async 的 return 值,又明确地作为函数的 return 值。您应该按如下方式进行:

fun main() {
    GlobalScope.launch(Dispatchers.Main) {
        val result1: Deferred<String> = async { F1(img) }
        val result2: Deferred<String> = async { F2(img) }
        doSomething(result1.await(), result2.await())
    }
}

suspend fun F1(img: Bitmap): String = suspendCoroutine { cont ->
    obj.process(img)
        .addOnSuccessListener { result ->
            cont.resume(result)
        }
}

suspend fun F2(img: Bitmap): String = suspendCoroutine { cont ->
    obj.process(img)
        .addOnSuccessListener { result ->
            cont.resume(result)
        }
}

此代码将您的基于侦听器的 API 转换为您只需调用并在 return 值中获得其结果的简单 suspend fun

您仍然可以使用 async 并行化这两个调用。

通常的建议是:研究结构化并发并使用比 GlobalScope 更好的东西。这种方式适用于大多数场景,但容易出现泄漏。这样做时,您还应该使用 suspendCancellableCoroutine 以便可以优雅地取消和清理正在进行的协程。