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

在RxJava的flatMap操作符中处理两种不同类型的问题

用Retrofit+RxJava实现跨模型的链式API请求

嘿,这个需求我之前也遇到过,用Retrofit结合RxJava的flatMap操作符完全能搞定!我给你一步步拆解实现过程:

1. 定义两个响应模型

首先得把两次请求对应的响应实体类写好,它们可以是完全不同的结构:

// 第一个请求的响应模型:返回包含目标URL的结构
public class GetURLResponse {
    private String url; // 假设接口返回的字段名是url

    // Getter方法
    public String getUrl() {
        return url;
    }
}

// 第二个请求的响应模型:和第一个结构完全不同
public class SecondResponse {
    private String content;
    private int code;

    // Getter方法
    public String getContent() {
        return content;
    }

    public int getCode() {
        return code;
    }
}

2. 编写APIService接口

接下来定义Retrofit的接口,注意第二个请求要用@Url注解来支持动态传入完整URL:

import io.reactivex.Observable;
import retrofit2.http.GET;
import retrofit2.http.Url;

public interface APIService {
    // 第一个请求:获取目标URL的接口
    @GET("api/initial-url")
    Observable<GetURLResponse> getURL();

    // 第二个请求:根据传入的URL发起请求,返回第二个响应模型
    @GET
    Observable<SecondResponse> fetchTargetData(@Url String targetUrl);
}

3. 实现链式请求逻辑

现在就可以用flatMap把两个请求串起来了,它会自动先执行第一个请求,拿到URL后再触发第二个请求:

// 先初始化Retrofit实例(记得配置RxJava适配器和Gson转换器)
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://your-base-domain.com/") // 第一个请求的基础URL
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 必须添加RxJava适配器
        .build();

APIService service = retrofit.create(APIService.class);

// 发起链式请求
service.getURL()
        // flatMap接收第一个请求的响应,返回第二个请求的Observable
        .flatMap(new Function<GetURLResponse, ObservableSource<SecondResponse>>() {
            @Override
            public ObservableSource<SecondResponse> apply(GetURLResponse getURLResponse) throws Exception {
                // 从第一个响应中取出URL,发起第二个请求
                return service.fetchTargetData(getURLResponse.getUrl());
            }
        })
        // 指定请求在IO线程执行
        .subscribeOn(Schedulers.io())
        // 指定回调在主线程处理(Android场景下需要)
        .observeOn(AndroidSchedulers.mainThread())
        // 订阅结果
        .subscribe(new Observer<SecondResponse>() {
            @Override
            public void onSubscribe(Disposable d) {
                // 可以保存这个Disposable,用于后续取消请求
            }

            @Override
            public void onNext(SecondResponse secondResponse) {
                // 这里处理第二个请求的响应数据
                String content = secondResponse.getContent();
                int code = secondResponse.getCode();
                // ... 业务逻辑处理
            }

            @Override
            public void onError(Throwable e) {
                // 处理任何请求环节的错误(第一个或第二个请求失败都会走到这里)
                e.printStackTrace();
                // 比如提示用户请求失败
            }

            @Override
            public void onComplete() {
                // 请求全部完成的回调
            }
        });

如果喜欢用Lambda表达式简化代码,上面的flatMap和subscribe可以写成更简洁的形式:

service.getURL()
        .flatMap(getURLResponse -> service.fetchTargetData(getURLResponse.getUrl()))
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
                secondResponse -> {
                    // 处理第二个请求的响应
                },
                throwable -> {
                    // 处理错误
                }
        );

关键注意点

  • @Url注解的使用:如果第一个请求返回的是完整URL(包含http/https前缀),用@Url注解的方法会忽略Retrofit的baseUrl,直接使用传入的URL发起请求,非常适合这种场景。
  • RxJava适配器:必须在Retrofit初始化时添加RxJava2CallAdapterFactory(或对应版本的适配器),否则接口方法无法返回Observable类型。
  • 异常统一处理:两个请求的异常都会走到onError回调里,如果你需要区分是第一个还是第二个请求失败,可以在flatMap里添加局部异常处理,比如用onErrorResumeNext。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:41:54