等待Kotlin中多个回调/ lambda的结果

问题描述 投票:0回答:1

我正在Kotlin制作应用程序。到目前为止,我的网络呼叫不必一起使用。现在,我需要同时进行两个网络通话,暂停直到收到他们的两个响应,然后继续执行。我正在尝试完成这样的事情:

    //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函数的函数头是:

fun asyncRequest(requestBuilder: RequestBuilder, completion: (resource: String?, error: ServiceError?) -> Unit) {

它只包装okhttp请求,并进行一些额外的处理/解析。通常,我只需要获取结果(资源)并在完成lambda中对其进行处理,但是由于我需要这两个值,因此无法在此处执行。我尝试做类似于this的操作,但是我的asyncRequest函数没有返回类型,因此我无法按照链接的方式进行异步/等待。

asynchronous kotlin okhttp
1个回答
0
投票

您可以使用协同程序Flow进行类似操作:

使用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)))
}

CombineFlowszip运算符:

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并消耗其结果

requestsResultFlow.collect { length ->
    // Consume the result here
    println("$length") // Here I print the number received
}

您拥有Flow文档here

© www.soinside.com 2019 - 2024. All rights reserved.