我如何等待 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 很好地解释了这里发生的事情。
在 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 很好地解释了这里发生的事情。