【问题标题】:How to wait multiple nested async calls by using of RxJava-Android?如何使用 RxJava-Android 等待多个嵌套的异步调用?
【发布时间】:2014-12-09 00:19:13
【问题描述】:

我是 RxJava 新手,这是我的情况,

  1. 发送请求 A,将得到 List<A> 回复
  2. 对于每个 A,发送请求 AA 并返回 AA,然后绑定 A 和 AA
  3. 有类似逻辑的 B & BB
  4. 只有在所有请求完成后才做某事

例子:

request(url1, callback(List<A> listA) {
    for (A a : listA) {
        request(url2, callback(AA aa) {
            a.set(aa);
        }
    }
}

A 和 B 是独立的

如何组织代码?我还使用 Retrofit 作为网络客户端。

【问题讨论】:

  • 处理程序和一个进度整数来控制您是否到达逻辑的末尾。
  • @Oliveira,是的,处理程序是一种解决方案,但我想知道 RxJava 是否可以提供更好、更简单的解决方案
  • “绑定 A 和 AA”到底是什么意思?所以你有一个请求会产生一个As列表,然后对于每个A都会有一个AA?此外,当您拥有 AA 时,您还需要 As 吗?您打算对 AA 做什么 - 是针对每个 AA 采取一项行动,还是针对所有 AA 采取联合行动?
  • @david.mihola,每个 A 有一个 AA,1-1 地图。由于服务器的限制,我无法在一个请求中同时获得 A 和 AA。 “绑定A和AA”就是AA取回后的动作,比如A.set(AA)

标签: android asynchronous rx-java


【解决方案1】:

好的,我认为这应该可以解决您问题的第一部分:

请注意,对flatMap 的第二次调用有两个参数——flatMap 的一个版本不仅为每个输入项生成一个 Observable,而且还采用第二个函数,该函数反过来将组合来自结果 Observable 与相应的输入项。

查看此标题下的第三张图以直观了解:

https://github.com/ReactiveX/RxJava/wiki/Transforming-Observables#flatmap-concatmap-and-flatmapiterable

Observable<A> obeservableOfAs = retrofitClient.getListOfAs()
.flatMap(new Func1<List<A>, Observable<A>>() {

    @Override
    public Observable<A> call(List<A> listOfAs) {
        return Observable.from(listOfAs);
    }

)}
.flatMap(new Func1<A, Observable<AA>>() {

    @Override
    public Observable<AA> call(A someA) {
        return retrofitClient.getTheAaForMyA(someA);
    }

},
new Func2<A, AA, A>() {

    @Override
    public A call(A someA, AA theAaforMyA) {
        return someA.set(theAaforMyA);
    }

})
...

从这里开始,我仍然不确定你想如何继续:你准备好订阅生成的 As 的 Observable 了吗?这样您就可以处理每个 As (onNext) 或等到所有操作都完成 (onCompleted)。

附录:最后要将所有项目收集到一个列表中,即将您的Observable&lt;A&gt; 转换为Observable&lt;List&lt;A&gt;&gt; 使用toList()

https://github.com/ReactiveX/RxJava/wiki/Mathematical-and-Aggregate-Operators#tolist

所以你有:

Observable<List<A>> observableOfListOfAs = observableOfAs.toList();

如果您需要对列表的构建进行更细粒度的控制,也可以使用reduce

https://github.com/ReactiveX/RxJava/wiki/Mathematical-and-Aggregate-Operators#reduce

对于 B,只需复制您用于 As 的整个流程。

然后您可以使用zip 等待两个流程完成:

Observable.zip(
    observableOfListOfAs,
    observableOfListOfBs,
    new Func2<List<A>, List<B>, MyPairOfLists>() {

        @Override
        public MyPairOfLists call(List<A> as, List<B> bs) {
            return new MyPairOfLists(as, bs);
        }
    }
)
.subscribe(new Subscriber<MyPairOfLists>() {

    // onError() and onCompleted() are omitted here

    @Override
    public void onNext(MyPairOfLists pair) {
        // now both the as and the bs are ready to use:

        List<A> as = pair.getAs();
        List<B> bs = pair.getBs();

        // do something here!
    }
});

我想你可以猜到MyPairOfLists的定义。

【讨论】:

  • 谢谢,Func2 for flatmap 看起来很棒!最后,我需要集合 A,我认为会有合并?那么B部分怎么样?
  • 所以你需要等到所有的A都有他们的AA,然后将它们收集到一个列表中?我认为 Bs 应该像 As 一样工作?当 List 和 List 都准备好时,应该执行最后一个操作吗?
  • 感谢您耐心的解释,现在一切正常! RxJava 确实让代码简洁明了!
  • @david.mihola 我正在使用 rxjava-async 制作一个异步网络请求列表,而不是使用 Retrofit,异常说我已经在主线程中使用它,但我已经订阅了新的线程。
  • 如果我理解正确的话,zip 会成对发射元素。我可以使用什么运算符代替 zip 在两个列表的末尾获得通知?我有两个请求列表(大小不同),最后只想执行一些代码。
猜你喜欢
  • 1970-01-01
  • 2017-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 2013-08-03
  • 1970-01-01
相关资源
最近更新 更多