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

如何等待2个并行Retrofit请求全部完成后执行后续操作?

并行请求等待全部完成实现方案

你当前分开调用两个请求独立订阅的写法,没法统一监听两个请求的完成状态,直接用RxJava的Single.zip操作符就能实现并行发起请求、等所有请求成功返回后再执行后续逻辑的效果,不需要大幅改动你现有的UseCase封装,因为基类已经提供了single()方法可以拿到构建好的Single实例。

ViewModel层改造

把原来两个独立执行、单独赋值的请求逻辑合并,新增统一的加载方法:

var config: List<Configuration> = emptyList()
var therapies: List<DtoTherapy> = emptyList()

fun loadAllData(
    onAllSuccess: (config: List<Configuration>, therapies: List<DtoTherapy>) -> Unit,
    onAnyError: (error: ApiError) -> Unit
) {
    // 构建两个请求的Single实例,这里不要调用execute/ executeWithError,否则会提前独立订阅
    val configSingle = getClientClientConfigUseCase.build(this).single()
    val therapySingle = getTherapiesUseCase.build(this).single()

    // zip会让两个Single在订阅后并行执行,等全部成功才会发送结果
    Single.zip(configSingle, therapySingle) { configRes: ClientConfigResponse, therapyRes: List<DtoTherapy> ->
        Pair(configRes, therapyRes)
    }
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnSubscribe {
            // 统一处理加载状态,比如显示全局loading
            onPrepareRequest(withLoader = true)
        }
        .doFinally {
            // 统一关闭加载状态
            onFinishRequest(withLoader = true)
        }
        .subscribe(
            { (configRes, therapyRes) ->
                // 两个请求都成功才会走到这里,先赋值
                config = configRes
                therapies = therapyRes
                // 回调通知页面所有数据加载完成
                onAllSuccess(config, therapies)
            },
            { throwable ->
                // 任意一个请求失败都会直接触发这里的错误回调
                val error = mapError(throwable) // 可以把基类的mapError抽到公共工具类复用
                onAnyError(error)
            }
        ).also {
            // 加入生命周期管理容器,避免内存泄漏
            compositeDisposable.add(it)
        }
}

注意:Single.zip不会串行执行请求,两个接口会在订阅后同时发起,总耗时等于两个请求中耗时更长的那个,完全匹配你说的1s+4s请求总耗时4s的场景。


Fragment层调用调整

删掉原来分开调用两个请求的代码,换成调用统一的合并加载方法:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
   
    setupUi(view)
    loadUserData()

    viewModel.loadAllData(
        onAllSuccess = { config, therapies ->
            // 这里就是两个接口全部成功返回的时机,直接写你的后续业务逻辑
            // 比如渲染配置项、加载理疗列表数据等
        },
        onAnyError = { error ->
            // 处理请求失败逻辑,比如弹出错误提示、重试按钮等
        }
    )
}

补充说明

  • 原来单独调用getClientProducts()、getTherapies()的方法可以保留,遇到只需要请求单个接口的场景正常用就行,不影响。
  • 如果后续要加更多并行接口,直接在zip里追加对应的Single实例即可,zip原生支持最多9个实例的合并重载,超过9个可以传Single集合做合并。
  • 不要在Fragment层直接拿UseCase做zip合并,请求逻辑统一收敛到ViewModel层,符合MVVM分层规范。

内容的提问来源于stack exchange,提问作者Mario Muresean

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 04:03:40