等待Kotlin中多个回调/lambda的结果 [英] Wait for result from multiple callbacks/lambdas in Kotlin
问题描述
我正在用Kotlin开发一个应用程序.到目前为止,我的网络呼叫不必一起使用.我现在在一个地方,需要同时进行两个网络通话,暂停直到收到他们的两个响应,然后继续执行.我正在尝试完成这样的事情:
I'm making an app in Kotlin. Up until this point, my networking calls didn't have to be used together. I am now in a spot where I need to make two concurrent networking calls, pause until I receive both of their responses, and then continue execution. I'm trying to accomplish something like this:
//first networking call, get resourceOne
var resourceOne : String?
Server.asyncRequest(RequestBuilder(endpoints.second, ids, params)) { resource: String?, error: ServiceError? ->
resourceOne = resource
}
//second networking call, get resourceTwo
var resourceTwo : String?
Server.asyncRequest(RequestBuilder(endpoints.third, ids, params)) { resource: String?, error: ServiceError? ->
resourceTwo = resource
}
//do something here wiith resourceOne and resourceTwo
asyncRequest函数的函数标头是:
The function header for my asyncRequest function is:
fun asyncRequest(requestBuilder: RequestBuilder, completion: (resource: String?, error: ServiceError?) -> Unit) {
它只是包装了一个okhttp请求并进行了一些额外的处理/解析.通常,我只需要获取结果(资源)并在完成lambda中对其进行处理,但是由于我需要这两个值,因此我无法在此处执行此操作.我尝试做类似于此,但是我的asyncRequest函数没有返回类型,因此我无法按照链接的方式进行异步/等待操作.
It just wraps around an okhttp request and does some extra processing/parsing. Normally I would just take the result (resource) and process it inside of the completion lambda, but since I need both values, I can't do that here. I've tried doing something similar to this but my asyncRequest function does not have a return type, so I have no way of doing the async/await the way the link does.
推荐答案
您可以使用协同程序和 Flow 来完成此操作,
You can do it with Coroutines along with Flow with something like this:
使用suspendCancellableCoroutine {...}
块将回调转换为可暂停的功能:
suspend fun <T> request(requestBuilder: RequestBuilder): T = suspendCancellableCoroutine { cont ->
Server.asyncRequest(requestBuilder) { resource: T, error: ServiceError? ->
if(error != null)
cont.resumeWithException(error) // Makes the Flow throw an exception
else
cont.resume(resource) // Makes the Flow emit a correct result
}
}
创建一个流程以发出第一个请求:
val resourceOneFlow = flow {
emit(request<String>(RequestBuilder(endpoints.second, ids, params)))
}
创建一个流程以进行第二次请求:
val resourceTwoFlow = flow {
emit(request<String>(RequestBuilder(endpoints.third, ids, params)))
}
组合和zip
运算符一起流:
val requestsResultFlow = resourceOneFlow.zip(resourceTwoFlow) { resourceOne, resourceTwo ->
// Build whatever you need with resourceOne and resourceTwo here and let it flow
"$resourceOne $resourceTwo".length // Here I concatenate both strings and return its length
}
使用collect
运算符激活/启动 Flow ,并使用其结果:
Activate/Start the Flow with the collect
operator and consume its result:
requestsResultFlow.collect { length ->
// Consume the result here
println("$length") // Here I print the number received
}
您拥有 Flow 文档 查看全文