说我有这个
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()
执行一些昂贵的调用(或有副作用)。我只想在 a.someCondition()
或 a 时进行此调用并初始化
。B.c
字段。如上所述,不满足 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;
});
}
最佳答案
您可以使用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)如果您取消订阅主要可观察量,forEach
无论如何,订阅都会继续,2) 如果您在 getC()
中指定了调度程序方法,主要可观察量可以在 forEach
之前完成已经完成了。
关于java - 惰性组合 Observables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47419576/