在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
相关产品推荐
相关产品推荐

