如何用RxJava链式调用Retrofit接口,关联电影与预告片数据?
用RxJava实现电影+预告片合并请求的正确姿势
刚好碰到过一模一样的需求,咱们一步步来拆解实现:
首先,你需要一个包装类来把电影和它的预告片绑定在一起——毕竟原有的Movie类应该没包含预告片字段对吧?
public class MovieWithVideos { private final Movie movie; private final List<Video> videos; public MovieWithVideos(Movie movie, List<Video> videos) { this.movie = movie; this.videos = videos; } // 记得加上getter方法,方便后续使用 public Movie getMovie() { return movie; } public List<Video> getVideos() { return videos; } }
接下来就是核心的RxJava流组合了,这里要用到几个关键操作符:
- 先获取全部电影列表:调用你的第一个Retrofit接口
movieService.fetchAll() - 拆分列表为单个电影:用
flatMapIterable把Single<List<Movie>>转换成Observable<Movie>,这样就能逐个处理每部电影 - 并行获取预告片并合并数据:用
flatMap(如果要串行处理就用concatMap)调用第二个接口获取预告片,然后用map把Movie和对应的List<Video>包装成MovieWithVideos - 收集结果为列表:最后用
toList()把所有MovieWithVideos重新组合成Single<List<MovieWithVideos>>
完整代码示例如下:
// 假设你的两个Retrofit服务实例是movieService和videoService Single<List<MovieWithVideos>> fetchMoviesWithVideos() { return movieService.fetchAll() // 把电影列表拆成单个电影的Observable .flatMapIterable(movies -> movies) // 并行处理每部电影的预告片请求 .flatMap(movie -> videoService.fetchByMovieId(movie.getId()) // 容错处理:如果某部电影的预告片请求失败,返回空列表,避免整个流崩溃 .onErrorReturnItem(Collections.emptyList()) // 把电影和预告片合并成包装类 .map(videos -> new MovieWithVideos(movie, videos))) // 把所有包装类收集成一个列表 .toList() // 可选:如果是Android项目,切换到主线程更新UI .observeOn(AndroidSchedulers.mainThread()) // 可选:指定请求在后台线程执行(Retrofit默认已经在后台,但显式指定更清晰) .subscribeOn(Schedulers.io()); }
关键细节说明:
flatMapvsconcatMap:flatMap会并行发起所有预告片请求,效率更高;如果需要严格按电影顺序串行请求,就换成concatMap- 错误处理:
onErrorReturnItem(Collections.emptyList())很重要,不然某一部电影的请求失败会导致整个流终止,这样即使个别请求失败,其他电影的数据依然能正常返回 - 线程调度:
subscribeOn(Schedulers.io())指定网络请求在IO线程执行,observeOn(AndroidSchedulers.mainThread())让最终结果在主线程回调(Android项目必备)
这样调用fetchMoviesWithVideos()就能得到包含所有电影及其预告片的列表了~
内容的提问来源于stack exchange,提问作者Dawid Fickenbaum
相关产品推荐
相关产品推荐

