使用RX进行呼叫,然后从第一次呼叫的结果进行多个并行呼叫

时间:2017-03-22 10:50:24

标签: android rx-java observable rx-java2

我必须调用返回项目列表的API。对于此列表中的每个项目,我必须调用另一个API(如果列表返回8个项目,我将必须进行8个并行调用)。

我最终必须返回一个列表,我将使用这8个并行调用的结果创建一个列表。

我如何使用RxJava做到这一点?我认为我必须使用flatMap将第一次调用的结果转换为Observable列表,然后我必须使用zip运算符进行并行调用,但我不确定。

请注意我使用RxJava2,没有lambdas表达式。

谢谢!

1 个答案:

答案 0 :(得分:3)

你可以这样做,例如, defer()允许您仅在订阅时获取数据,然后在项目列表中创建发出所有项目(逐个)的Observable。
然后flatMap()将创建Observable来获取每个项目的数据,现在您将拥有发出数据对象的Observable。 为了收集它,您可以使用toList()发出单个对象(List),该对象将包含每个Data提取的所有Observable

注意,为了并行执行,fetchDataFromItem()订阅Schedulers.io()非常重要,即使是在io上订阅了所有流。

Observable.defer(new Callable<ObservableSource<Item>>() {
        @Override
        public ObservableSource<Item> call() throws Exception {
            List<Item> items = getItems();
            return Observable.fromIterable(items);
        }
    })
            .flatMap(new Function<Item, ObservableSource<Data>>() {
                @Override
                public ObservableSource<Data> apply(@NonNull Item item) throws Exception {
                    return fetchDataFromItem(item);
                }
            })
            .toList()
            .subscribe(new Consumer<List<Data>>() {
                @Override
                public void accept(@NonNull List<Data> objects) throws Exception {
                //do something with the list of all fetched data
                }
            });

更新:

如果提取的项目已经Observable,则defer()可以替换为flatMapIterable(),其中包含单个项目列表并将其转换为多个项目的Observable:

getItemsObservable()
        .flatMapIterable(new Function<List<Item>, Iterable<Item>>() {
            @Override
            public Iterable<Item> apply(@NonNull List<Item> items) throws Exception {
                return items;
            }
        })
        .flatMap(new Function<Item, ObservableSource<Data>>() {
            @Override
            public ObservableSource<Data> apply(@NonNull Item item) throws Exception {
                return fetchDataFromItem(item);
            }
        })
        .toList()
        .subscribe(new Consumer<List<Data>>() {
            @Override
            public void accept(@NonNull List<Data> objects) throws Exception {
                //do something with the list of all fetched data
            }
        });