如何在for循环中等待全部Volley请求完成后再返回结果列表
问题核心
你当前的代码存在两个核心问题:
- Volley本身是基于回调的异步API,协程的
launch方法启动的是异步任务,不会阻塞当前挂起函数的返回流程,因此函数会直接返回还未填充数据的空列表 - 没有对多个并行的能力请求做等待逻辑,无法感知所有请求完成的时机
解决方案
需要先将Volley的回调式请求封装为挂起函数,再结合async + awaitAll等待所有并行请求完成后再返回结果。
第一步:封装Volley请求为挂起函数
首先把JsonObjectRequest的回调逻辑转换为协程可等待的挂起调用:
import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine suspend fun RequestQueue.executeJsonObjectRequest(method: Int, url: String): JSONObject = suspendCoroutine { continuation -> val request = JsonObjectRequest( method, url, null, { response -> continuation.resume(response) }, { error -> continuation.resumeWithException(error) } ) add(request) }
第二步:重写获取能力列表的方法
suspend fun getListOfAbility(pokemon: Pokemon) : List<Ability> = coroutineScope { // 第一步:请求宝可梦基础信息,挂起等待结果返回 val pokemonResponse = requestQueue.executeJsonObjectRequest(Request.Method.GET, "$pokemonUrl${pokemon.id}") // 解析能力列表 val abilitiesJO = pokemonResponse.getJSONObject("abilities") val abilityObjectType = object : TypeToken<List<PokemonGson.AbilityObjectGson>>() { }.type val abilityListGson = Gson().fromJson<List<PokemonGson.AbilityObjectGson>>(abilitiesJO.toString(), abilityObjectType) // 第二步:对每个能力并行发起请求,用async包裹每个请求 val abilityDeferredList = abilityListGson.mapIndexed { index, abilityObjectGson -> async(Dispatchers.IO) { val abilityJson = requestQueue.executeJsonObjectRequest(Request.Method.GET, abilityObjectGson.ability.url) val abilityType = object : TypeToken<AbilityGson>() { }.type val abilityGson = Gson().fromJson<AbilityGson>(abilityJson.toString(), abilityType) Ability(abilityGson, abilityListGson[index].is_hidden) } } // 等待所有能力请求全部完成,收集结果返回 abilityDeferredList.awaitAll() }
逻辑说明
- 封装的
executeJsonObjectRequest扩展函数通过suspendCoroutine将回调式API转为挂起调用,请求过程不会阻塞线程,结果返回后才会继续执行后续代码 - 外层使用
coroutineScope,会等待作用域内所有异步任务完成后再返回结果,同时继承当前挂起函数的协程上下文,不需要手动创建额外的协程作用域 - 所有能力请求通过
async并行发起,awaitAll会阻塞协程直到所有请求全部完成,最终返回完整的能力列表 - 你可以根据需要调整错误处理逻辑,比如捕获请求异常返回默认值,或者给方法增加错误返回类型
内容的提问来源于stack exchange,提问作者Simone
相关产品推荐
相关产品推荐

