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

如何用RxJava、RxKotlin和Retrofit的flatMap实现API顺序调用?

可行方案:用RxJava/RxKotlin + Retrofit的flatMap串联顺序API调用

当然有完美的解决方案!你想要的正是RxJava中flatMap操作符的核心场景——它就是用来把多个Observable(或Flowable)串联起来,让前一个的输出直接作为后一个的输入,完全不需要为每个API写独立的订阅逻辑。结合Retrofit的Rx支持,整个流程会非常简洁。

下面我一步步给你拆解实现思路和代码示例:

1. 先定义Retrofit的API接口

首先要确保你的Retrofit接口方法返回RxJava类型(比如Observable或Flowable),而不是传统的Call:

interface ApiService {
    // API1: 接收Spinner选中的参数,返回Observable<Api1Response>
    @GET("api/endpoint1")
    fun callApi1(@Query("selectedOption") option: String): Observable<Api1Response>

    // API2: 接收API1的输出作为参数,返回Observable<Api2Response>
    @POST("api/endpoint2")
    fun callApi2(@Body request: Api1Response): Observable<Api2Response>

    // API3: 接收API2的输出作为参数,返回Observable<Api3Response>
    @POST("api/endpoint3")
    fun callApi3(@Body request: Api2Response): Observable<Api3Response>
}

2. 把Spinner的选中事件转换成Observable

要触发整个流程,我们需要把Spinner的选择事件包装成Observable。这里有两种实现方式:

方式一:用RxBinding(推荐,简化View事件转换)

// 先添加RxBinding依赖,直接把Spinner的选中事件转成Observable
val spinnerSelectionObservable = RxSpinner.itemSelections(spinner)
    .map { it.toString() } // 把选中的Item转换成API1需要的参数格式

方式二:手动实现(无需额外依赖)

val spinnerSelectionObservable = Observable.create<String> { emitter ->
    spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
        override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
            val selectedOption = parent?.getItemAtPosition(position).toString()
            emitter.onNext(selectedOption)
        }

        override fun onNothingSelected(parent: AdapterView<*>?) {
            // 可选:处理未选中的情况
        }
    }
    // 销毁时取消监听,避免内存泄漏
    emitter.setCancellable {
        spinner.onItemSelectedListener = null
    }
}

3. 用flatMap串联三个API调用

这一步是核心!通过flatMap把三个API的Observable串联起来,每一步的输出自动作为下一步的输入:

// 初始化ApiService实例(假设你已经配置好Retrofit)
val apiService = Retrofit.Builder()
    .baseUrl("https://your-base-url.com/")
    .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) // 必须添加Rx的CallAdapter
    .build()
    .create(ApiService::class.java)

// 串联整个调用流程
spinnerSelectionObservable
    .distinctUntilChanged() // 避免重复选中同一选项时重复触发请求
    .flatMap { selectedOption ->
        // 第一步:调用API1,传入Spinner选中的参数
        apiService.callApi1(selectedOption)
    }
    .flatMap { api1Response ->
        // 第二步:用API1的输出调用API2
        apiService.callApi2(api1Response)
    }
    .flatMap { api2Response ->
        // 第三步:用API2的输出调用API3
        apiService.callApi3(api2Response)
    }
    .subscribeOn(Schedulers.io()) // 网络请求在IO线程执行
    .observeOn(AndroidSchedulers.mainThread()) // 结果回调回到主线程更新UI
    .subscribe(
        // 最终成功回调:API3执行完成后的处理
        { api3Response ->
            Toast.makeText(context, "API3调用成功:${api3Response.data}", Toast.LENGTH_SHORT).show()
            // 这里可以添加UI更新逻辑
        },
        // 错误回调:任何一步出错都会触发这里
        { error ->
            Log.e("ApiFlow", "流程出错:${error.message}", error)
            Toast.makeText(context, "请求失败:${error.message}", Toast.LENGTH_SHORT).show()
        }
    )

关键说明

  • flatMap的核心作用:它会订阅前一个Observable的输出,然后返回一个新的Observable(即下一个API的请求),天然实现了顺序依赖的调用逻辑。
  • 线程管理:subscribeOn(Schedulers.io())确保网络请求在后台线程执行,observeOn(AndroidSchedulers.mainThread())让结果回到主线程,避免ANR。
  • 统一错误处理:整个流程中任何一个API调用失败,都会直接触发错误回调,不用为每个API单独写异常处理。
  • 防重复请求:distinctUntilChanged()可以过滤掉重复的选中事件,避免不必要的重复调用。

这样一来,你就不需要为每个API写独立的Observer和订阅代码了,整个流程是链式的,逻辑清晰且易于维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:46:51