如何在 Kotlin 协程中等待其他事件?

Sea*_*ean 6 android kotlin kotlin-coroutines

在 Kotlin 中,使用协程,假设我有一项工作是通过单击按钮开始的,并且在onStop调用活动之前不应结束。

看起来像这样的东西:

button.setOnClickListener {
    CoroutineScope(...).launch{
        print("Button clicked")

        // How to wait for "onStop()" ?

        print("Activity stopped")
    }
}
Run Code Online (Sandbox Code Playgroud)

上述场景只是一般需要以函数调用 ( ) 的形式合并来自 SDK 内部的异步事件的示例onStop()

应该怎么做呢?谢谢 :]

vod*_*dan 11

我会为按钮创建一个特殊通道,然后向其发送一些内容onStop(0)并在代码中等待它:

val onStopChannel = Channel<Int>()

fun onStop() {
    onStopChannel.offer(0)
}

button.setOnClickListener {
    CoroutineScope(...).launch{
        print("Button clicked")

        onStopChannel.receive()

        print("Activity stopped")
    }
}
Run Code Online (Sandbox Code Playgroud)

任何其他可观察的也可以工作。


小智 5

为了解决以下问题:

一般需要以函数调用的形式合并来自 SDK 的异步事件

我想补充一点,标准库将来自另一个不使用协程的库或 API 的异步回调或 future 集成到您自己使用协程的代码中的方法是函数suspendCoroutine。它挂起当前协程的执行,采用非挂起 lambda,在其中注册回调/侦听器,调用时将通过对象告诉协程使用Continuation从打回来。

例如,在网络请求的情况下:

suspend fun useValueFromApiCall(apiCall: Call<Thing>) {
    val myThing: Thing = suspendCoroutine<Thing> { continuation ->
        apiCall.enqueue(object: Callback<Thing> {
            override fun onResponse(call: Call<Thing>, response: Response<Thing>) {
                continuation.resume(response.body()) // assign response.body() to myThing
            }
            override fun onFailure(call: Call<Thing>, t: Throwable) {
                continuation.resumeWithException(t) // throw t
            }
        })
    }
    // coroutine will suspend execution until the API call returns and
    // either myThing contains the response or an exception was thrown
    myThing.doSomething()
}
Run Code Online (Sandbox Code Playgroud)

这是一个演讲的片段,很好地解释了这里发生的事情。