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

How do I wait for other events in Kotlin coroutines?

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

看起来像这样的东西:

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

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

        print("Activity stopped")
    }
}

以上场景只是一般需要合并的一个例子 来自 SDK 中函数调用形式的异步事件 (onStop())。

应该怎么做?谢谢:]

我会为按钮创建一个特殊通道,而不是从 onStop(0) 向它发送内容并在您的代码中等待它:

val onStopChannel = Channel<Int>()

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

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

        onStopChannel.receive()

        print("Activity stopped")
    }
}

任何其他 observable 也可以。

我会让我的工作等待 join() 函数,然后在 onStop() 回调中取消它。 类似于:

class MainActivity : AppCompatActivity() {
    private var job: Job = Job()
    private val mainDispatchersContext = CoroutineScope(Dispatchers.Main)
    private val coroutineContext = CoroutineScope(Dispatchers.Main + job)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mainDispatchersContext.launch {
            doJob()
        }
    }

    private suspend fun doJob() {
        coroutineContext.launch {
            // do something
            Log.v(TAG, "Job started")
            job.join()
            Log.v(TAG, "This line is not executed")
        }
    }

    override fun onStop() {
        super.onStop()
        job.cancel()
        Log.v(TAG, "Job end")
    }

    companion object{
        const val TAG = "MainActivity"
    }
}

解决以下问题:

a general need to incorporate asynchronous events that come from within an SDK in the form of a function invocation

我想补充一点,标准库将异步回调或来自另一个库的期货或 API 不使用协程的方法集成到您自己使用协程的代码中的方法是 suspendCoroutine 功能。它暂停当前协程的执行,接受一个非暂停的 lambda,你在其中注册你的 callbacks/listeners,它在调用时将通过 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()
}

Here is a snippet 很好地解释了这里发生的事情。