在Kotlin中,使用协同程序,我有一个工作是从单击按钮开始的,并且不应该在调用活动的onStop
之前结束。
看起来像这样的东西:
button.setOnClickListener {
CoroutineScope(...).launch{
print("Button clicked")
// How to wait for "onStop()" ?
print("Activity stopped")
}
}
以上场景只是一般需要合并的一个示例
来自SDK内部的异步事件,以函数调用(onStop()
的形式出现。
应该怎么做?谢谢:]
答案 0 :(得分:3)
我会为按钮创建一个特殊的通道,而不是从onStop(0)
发送一些东西给它,然后在您的代码中等待它:
val onStopChannel = Channel<Int>()
fun onStop() {
onStopChannel.offer(0)
}
button.setOnClickListener {
CoroutineScope(...).launch{
print("Button clicked")
onStopChannel.receive()
print("Activity stopped")
}
}
其他可观察到的东西也可以工作。
答案 1 :(得分:2)
要解决以下问题:
通常需要合并来自内部的异步事件 函数调用形式的SDK
我想补充一点,标准库将来自另一个不使用协程的库或API的异步回调或期货集成到您自己的使用协程的代码中的方法是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()
}
Here is a snippet很好地解释了这里的情况。
答案 2 :(得分:0)
我将使用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"
}
}