RxJava实现列表Observable转Observable列表并合并(Android开发场景)
嘿,我刚好在开发Hacker News阅读器时处理过一模一样的需求,用RxJava来实现这套数据流非常丝滑,我给你一步步拆解并附上代码示例:
核心实现思路
我们需要分三步来搭建这个数据流链:
- 调用Hacker News的
/topstories接口,拿到返回的故事ID列表 - 将每个ID单独映射为获取对应Story详情的Observable
- 等待所有详情请求完成后,合并成一个完整的Story列表Observable
具体代码实现
首先,我们需要定义Retrofit接口来对接Hacker News的API:
public interface HackerNewsApi { // 获取Top Stories的ID列表 @GET("/topstories.json") Observable<List<Integer>> getTopStoryIds(); // 根据ID获取单个Story详情 @GET("/item/{id}.json") Observable<Story> getStory(@Path("id") int storyId); }
接下来,在数据仓库或者业务逻辑层里组装RxJava的数据流:
public class HackerNewsRepository { private final HackerNewsApi api; public HackerNewsRepository(HackerNewsApi api) { this.api = api; } public Observable<List<Story>> getTopStories() { return api.getTopStoryIds() // 把ID列表拆分成单个ID的Observable流 .flatMapIterable(ids -> ids) // 对每个ID发起详情请求,这里用flatMap保证请求可以并行执行 .flatMap(storyId -> api.getStory(storyId)) // 等待所有详情请求完成后,把结果收集成一个List<Story> .toList() // 处理可能出现的异常,比如网络请求失败 .onErrorReturn(throwable -> Collections.emptyList()); } }
关键操作符说明
flatMapIterable: 把上游发射的List<Integer>拆分成一个个单独的Integer(也就是每个Story ID),这样我们可以逐个处理flatMap: 把每个Story ID转换成获取详情的Observable,并且这些请求是并行执行的,能提升整体请求效率toList: 等待所有上游的Story详情都发射完成后,将它们合并成一个List<Story>发射出去,完美符合你“所有请求完成时发射List”的需求
使用方式
在ViewModel或者Presenter里调用这个方法,然后订阅即可:
repository.getTopStories() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(stories -> { // 拿到所有Top Story的列表,更新UI updateUi(stories); }, throwable -> { // 处理异常情况 showError(); });
这样整个数据流就跑通啦,从获取ID列表到批量请求详情,再到合并结果,完全用RxJava的操作符串联起来,代码简洁还自带线程调度~
内容的提问来源于stack exchange,提问作者Selenir
相关产品推荐
相关产品推荐

