Android 进行多个协同路由API调用并等待所有调用
因此,通常当您必须进行不同的API调用并等待时,您会执行以下操作:Android 进行多个协同路由API调用并等待所有调用,android,retrofit,coroutine,kotlin-coroutines,suspend,Android,Retrofit,Coroutine,Kotlin Coroutines,Suspend,因此,通常当您必须进行不同的API调用并等待时,您会执行以下操作: viewModelScope.launch { withContext(dispatcherProvider.heavyTasks) { val apiResponse1 = api.get1() //suspend function val apiResponse2 = api.get2() //suspend function if (apiResponse1.isS
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)
}
}
viewModelScope.launch{
withContext(dispatcherProvider.heavyTasks){
val multipleIds=listOf(1,2,3,4,5,…)
val content=arrayListOf()
multipleIds.forEach{id->
val apiResponse1=api.get1(id)//挂起函数
if(apiResponse1.issusccessful()){
content.find{it.id==id}.enable=true
}
}
liveData.postValue(内容)
}
}
第二种方法的问题是,它将遍历
multipleID
列表的所有ID并进行异步调用,但内容可能会在这之前发布。我如何等待每个循环的所有响应完成,然后才查看内容的postValue
?而不是forEach
,使用map
并在{}块内执行同样的操作。将映射结果保存到变量并发布此变量。为了获得并发行为,您需要为每个id启动一个新的协同程序。您可以将多个id
和内容
移动到与上下文
块的外部。您还可以在withContext
块之后发布结果,因为withContext
是一个挂起函数,所以在内部创建的每个协同程序都必须在发布结果之前完成
viewModelScope.launch {
val multipleIds = listOf(1, 2, 3, 4, 5, ..)
val content = arrayListOf<CustomObj>()
withContext(dispatcherProvider.heavyTasks) {
multipleIds.forEach { id ->
launch {
val apiResponse = api.get(id) //suspend function
if (apiResponse.isSuccessful()) {
content.find { it.id == id }?.enable = true
}
}
}
}
liveData.value = content
}
viewModelScope.launch{
val multipleIds=listOf(1,2,3,4,5,…)
val content=arrayListOf()
withContext(dispatcherProvider.heavyTasks){
multipleIds.forEach{id->
发射{
val apiResponse=api.get(id)//挂起函数
if(apiResponse.issusccessful()){
content.find{it.id==id}?.enable=true
}
}
}
}
liveData.value=内容
}
确保完成两个异步任务的首选方法是使用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)
}
}
当我在liveData.value上设置断点时,使用async
并在主题上等待可能会有所帮助-它总是按预期工作,所有列表项都为true(api.get(id)-已调用且响应已得到),但当我在没有断点的情况下运行代码时,所有列表项都为false(日志显示api调用成功),这意味着,这一反应来得晚。这是行不通的。
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)
}
}