考虑一个异步API,该API报告其操作进度:
suspend fun operationWithIO(input: String, progressUpdate: (String) -> Unit): String {
withContext(Dispatchers.IO) {
// ...
}
}
是否可以实现对progressUpdate
的调用,以便在调用者的调度程序上处理回调?还是有更好的方法将状态更新回传给呼叫者?
答案 0 :(得分:2)
您应该在频道上发送进度更新。这样一来,呼叫者就可以使用所需的任何调度程序来监听频道。
suspend fun operationWithIO(input: String, progressChannel: Channel<String>): String {
withContext(Dispatchers.IO) {
// ...
progressChannel.send("Done!")
progressChannel.close()
}
}
呼叫者可以通过执行以下操作来使用它:
val progressChannel = Channel<String>()
someScope.launch {
operationWithIO(input, progressChannel)
}
// Remember the call to progressChannel.close(), so that this iteration stops.
for (progressUpdate in progressChannel) {
println(progressUpdate)
}
答案 1 :(得分:0)
如何包装回调函数并调用包装的函数:
/** Return a new callback that invokes this callback on the current context. */
suspend fun <T> ((T) -> Unit).onCurrentContext(): (T) -> Unit =
coroutineContext.let { context ->
{ value: T ->
runBlocking {
launch(context) {
this@onCurrentContext.invoke(value)
}
}
}
}
/** Perform a background operation, delivering status updates on the caller's context. */
suspend fun operationWithIO(statusUpdate: (String) -> Unit): String {
val cb = statusUpdate.onCurrentContext()
return withContext(Dispatchers.IO) {
cb("Phase 1")
delay(150)
cb("Phase 2")
delay(150)
"Result"
}
}
// In use
runBlocking {
val result = operationWithIO {
println("received callback status $it")
}
println("result is $result")
}