You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在for循环中等待全部Volley请求完成后再返回结果列表

问题核心

你当前的代码存在两个核心问题:

  1. Volley本身是基于回调的异步API,协程的launch方法启动的是异步任务,不会阻塞当前挂起函数的返回流程,因此函数会直接返回还未填充数据的空列表
  2. 没有对多个并行的能力请求做等待逻辑,无法感知所有请求完成的时机
解决方案

需要先将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 21:06:05