因此,通常当您必须进行不同的 API 调用并等待时,您会执行以下操作:
viewModelScope.launch {
withContext(dispatcherProvider.heavyTasks) {
val apiResponse1 = api.get1() //suspend function
val apiResponse2 = api.get2() //suspend function
if (apiResponse1.isSuccessful() && apiResponse2.isSuccessful() { .. }
}
}
但是如果我必须使用不同的参数执行多个并发的相同 API 调用会发生什么:viewModelScope.launch {
withContext(dispatcherProvider.heavyTasks) {
val multipleIds = listOf(1, 2, 3, 4, 5, ..)
val content = arrayListOf<CustomObj>()
multipleIds.forEach { id ->
val apiResponse1 = api.get1(id) //suspend function
if (apiResponse1.isSuccessful()) {
content.find { it.id == id }.enable = true
}
}
liveData.postValue(content)
}
}
第二种方法的问题是它将遍历 multipleIds
的所有 ID。列出并进行异步调用,但 content
可能会在此之前发布。如何等待每个循环的所有响应完成,然后才 postValue
要查看的内容?
最佳答案
确保完成几个异步任务的首选方法是使用 coroutineScope
.它将暂停直到所有子作业,例如所有调用 launch
或 async
, 已完成。
viewModelScope.launch {
withContext(dispatcherProvider.heavyTasks) {
val multipleIds = listOf(1, 2, 3, 4, 5, ..)
val content = arrayListOf<CustomObj>()
coroutineScope {
multipleIds.forEach { id ->
launch { // this will allow us to run multiple tasks in parallel
val apiResponse = api.get(id)
if (apiResponse.isSuccessful()) {
content.find { it.id == id }.enable = true
}
}
}
} // coroutineScope block will wait here until all child tasks are completed
liveData.postValue(content)
}
}
如果您对这种相当隐含的方法感到不舒服,您还可以使用更实用的方法,将您的 id 映射到 Deferred
的列表。使用 async
然后等待他们所有人。这也将允许您并行运行所有任务,但最终会得到一个按正确顺序排列的结果列表。viewModelScope.launch {
withContext(dispatcherProvider.heavyTasks) {
val multipleIds = listOf(1, 2, 3, 4, 5, ..)
val content = arrayListOf<CustomObj>()
val runningTasks = multipleIds.map { id ->
async { // this will allow us to run multiple tasks in parallel
val apiResponse = api.get(id)
id to apiResponse // associate id and response for later
}
}
val responses = runningTasks.awaitAll()
responses.forEach { (id, response) ->
if (response.isSuccessful()) {
content.find { it.id == id }.enable = true
}
}
liveData.postValue(content)
}
}
关于android - 进行多个协程 API 调用并等待所有调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62892071/