说我有这个
Observable<A> getA() {
return Observable.just(new A());
}
Observable<C> getC() {
// ... some expensive call
return Observable.just(new C());
}
Observable<B> getB() {
return getA()
.map(a -> {
if (a.someCondition()) {
final B b = new B();
b.setSomeFields(...);
return b;
}
if (a.otherCondition()) {
final B b = new B();
b.setOtherFields(...);
return b;
}
final B b = new B(...);
b.setC(getC().toBlocking().single());
return b;
});
}
其中getC()
执行一些昂贵的调用(或有副作用)。我想进行此调用并仅在B.c
或a.someCondition()
不符合时初始化a. otherCondition()
字段,如上所述。
如何重写以摆脱.toBlocking()
?
我想到的一种方法是压缩getA()
和getC()
:
Observable<B> getB() {
return Observable.zip(getA(), getC(), (a, c) -> Tuple.of(a, c))
.map(tuple -> {
final A a = tuple._1;
final C c = tuple._2;
if (a.someCondition()) {
final B b = new B();
b.setSomeFields(...);
return b;
}
if (a.otherCondition()) {
final B b = new B();
b.setOtherFields(...);
return b;
}
final B b = new B(...);
b.setC(c);
return b;
});
}
但是这会一直带来昂贵的通话费用。同时也难以阅读有更复杂条件的地方,或者当我有超过2个Observables要拉链时。
修改:
@ ESala的答案有效,但有时从map
切换到flatMap
需要进行大量更改。下面的解决方案是否也有效?
Observable<B> getB() {
return getA()
.map(a -> {
if (a.someCondition()) {
final B b = new B();
b.setSomeFields(...);
return b;
}
if (a.otherCondition()) {
final B b = new B();
b.setOtherFields(...);
return b;
}
final B b = new B(...);
getC().forEach(c -> b.setC(c));
return b;
});
}
答案 0 :(得分:1)
您可以使用flatMap
代替map
,这样就可以避免使用toBlocking
,只有在必要时才会拨打昂贵的电话。
示例:
Observable<B> getB() {
return getA()
.flatMap(a -> { // <-- flatMap here
if (a.someCondition()) {
final B b = new B();
b.setSomeFields(...);
return Observable.just(b); // <-- wrap in observable
}
if (a.otherCondition()) {
final B b = new B();
b.setOtherFields(...);
return Observable.just(b); // <-- wrap in observable
}
return getC().map(c -> { // <-- expensive call executed
B b = new B(...); // only when necessary
b.setC(c);
return b;
});
});
}
关于问题编辑的更新:
我认为切换到flatMap
不需要进行大量更改。你有一个具体的例子吗?
关于编辑中的替代解决方案: 可以在这种情况下工作,但我不推荐它。
通过执行此操作,您正在创建另一个订阅,该订阅不受主要可观察流程的管理,并且通常不会发生这种情况。 forEach
运算符会返回一个Disposable
,它会挂在那里!
它可能导致的一些问题包括:1)如果您取消订阅主要的observable,forEach
订阅将继续,2)如果您在getC()
方法中指定了调度程序,则主要的observable可以在forEach
完成之前完成。