考虑一个报告其操作进度的异步API:
suspend fun operationWithIO(input: String, progressUpdate: (String) -> Unit): String {
withContext(Dispatchers.IO) {
// ...
}
}
是否可以实现对progressUpdate
的调用,以便在调用者的调度程序上处理回调?或者有更好的方法将状态更新传递给调用者吗?
您应该在频道上发送进度更新。这将允许呼叫者使用它想要的任何调度员来收听频道。
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)
}
如何包装回调函数并调用包装函数:
/** 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) {
[email protected](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")
}