我可以有条件地“合并”一个单一的Observable吗?

时间:2017-03-27 03:02:31

标签: rx-java2

我是RxJava的新人,我在如何做以下事情时遇到了一些麻烦。

  • 我正在使用Retrofit来调用一个网络请求,该请求返回Single<Foo>,这是我最终希望通过 Subscriber 实例消费的类型(称之为SingleFooSubscriber })
  • Foo的内部属性items类型为List<String>
  • 如果Foo.items不为空,我想为每个值调用单独的并发网络请求。 (SingleFooSubscriber这些请求的实际结果无关紧要,因为结果将在外部缓存。
  • 只有在提取SingleFooSubscriber.onComplete()和所有Foo时才应调用
  • Foo.items

fetchFooCall     .subscribeOn(Schedulers.io())

// Approach #1...
// the idea here would be to "merge" the results of both streams into a single
// reactive type, but i'm not sure how this would work given that the item emissions
// could be far greater than one. using zip here i don't think it would every 
// complete.

.flatMap { foo ->
    if(foo.items.isNotEmpty()) {
        Observable.zip(
                Observable.fromIterable(foo.items),
                Observable.just(foo),
                { source1, source2 -> 
                    // hmmmm...
                }
        ).toSingle()

    } else {
        Single.just(foo)
    }
}

// ...or Approach #2...
// i think this would result in the streams for Foo and items being handled sequentially,
// which is not really ideal because
// 1) i think it would entail nested streams (i get the feeling i should be using flatMap 
//    instead)
// 2) and i'm not sure SingleFooSubscriber.onComplete() would depend on the completion of
//    the stream for items

.doOnSuccess { data ->
    if(data.items.isNotEmpty()) {
        // hmmmm...
    }
}

.observeOn(AndroidSchedulers.mainThread())
.subscribe(
    { data  -> /* onSuccess() */ },
    { error -> /* onError()   */ }
)

任何有关如何处理此问题的想法都将非常感谢!

奖励积分:在尝试提出解决方案时,我开始质疑使用Single反应类型与Observable反应类型的决定。我的数据流中的大多数(除了这一Foo.items个案例之外的所有情况?)实际上都围绕着消耗单个事物的实例,因此我倾向于使用Single来表示我的流,因为我认为它会在代码周围添加一些语义清晰度。任何人都有关于何时使用一个与另一个的一般指导?

1 个答案:

答案 0 :(得分:2)

您需要嵌套flatMap,然后转换回Single

retrofit.getMainObject()
  .flatMap(v ->
     Flowable.fromIterable(v.items)
       .flatMap(w ->
         retrofit.getItem(w.id).doOnNext(x -> w.property = x)
       )
       .ignoreElements()
       .toSingle(v)
)