等待Kotlin中多个回调/lambda的结果 [英] Wait for result from multiple callbacks/lambdas in Kotlin

查看:354
本文介绍了等待Kotlin中多个回调/lambda的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用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 文档 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆