Android 当组合多个观测值时,如何急切地返回RxJava?
假设我有3个条件要检查。在命令式编程中,我会写Android 当组合多个观测值时,如何急切地返回RxJava?,android,rx-java,Android,Rx Java,假设我有3个条件要检查。在命令式编程中,我会写 boolean foo(A a, B b, C c){ if(a.meetsCriteria()){ return true; } if(b.meetsCriteria()){ return true; } if(c.meetsCriteria()){ return true; } return false; } 下面是我愚蠢的尝试,试图将上述内容转换为反应式 Observable<Boolean> foo(A a,
boolean foo(A a, B b, C c){
if(a.meetsCriteria()){ return true; }
if(b.meetsCriteria()){ return true; }
if(c.meetsCriteria()){ return true; }
return false;
}
下面是我愚蠢的尝试,试图将上述内容转换为反应式
Observable<Boolean> foo(A a, B b, C c){
Observable.zip(
a.meetsCriteria(),
b.meetsCriteria(),
c.meetsCriteria(),
(bool1, bool2, bool3)->{return bool1 | bool2 | bool3;}
}
可观测的foo(A、B、C){
可观察的.zip(
a、 MeetCriteria(),
b、 MeetCriteria(),
c、 MeetCriteria(),
(bool1,bool2,bool3)->{返回bool1 | bool2 | bool3;}
}
这里的问题是调用了所有3个
MeetCriteria()
方法,因此此实现不会立即返回。我希望B和C的MeetCriteria()
在A.MeetCriteria()时不执行
返回true。正确的无功转换是什么?您只需要另一个运算符。您可以使用一系列平面图,而不是Observable.zip
:
a.meetsCriteria().flatMap(
resa -> resa ? Observable.just(true) : b.meetsCriteria().flatMap(
resb -> resb ? Observable.just(true) : c.meetsCriteria()
)
)
然而,在最坏的情况下,这实际上会使代码串行化(所有三个标准都是错误的)
因此,为了从反应式编程中获益,您必须同时运行所有这些程序。我提出了以下想法:
合并
可观察对象(它们将并行运行)filter
outtrue
它们中任何一个发出的值defaultIfEmpty(false)
操作符,这是当所有观察值发出false
first()
,我们就可以得到一个布尔值Observable<Boolean> a = Observable.just(false).delay(15, TimeUnit.SECONDS);
Observable<Boolean> b = Observable.just(true).delay(5, TimeUnit.SECONDS);
Observable<Boolean> c = Observable.just(false).delay(50, TimeUnit.DAYS);
final Observable<Boolean> res = Observable.merge(a, b, c)
.filter(item -> item == true)
.defaultIfEmpty(false)
.first();
System.err.println(res.toBlocking().first());
,你注定要等50天才能让可观察的c
完成:)好吧,很明显,我们无法知道c
是否会为合并操作符发出任何信息,所以这是不可避免的
当然,如果您尝试以下方法,您仍然可以从并行性中获益:
Observable<Boolean> a = Observable.just(false).delay(10, TimeUnit.SECONDS);
Observable<Boolean> b = Observable.just(false).delay(10, TimeUnit.SECONDS);
Observable<Boolean> c = Observable.just(false).delay(10, TimeUnit.SECONDS);
Observable a=可观测。刚好(假)。延迟(10,时间单位。秒);
可观测b=可观测的。刚好(错误)。延迟(10,时间单位。秒);
可观测的c=可观测的。刚好(错误)。延迟(10,时间单位。秒);
,总运行时间约为10秒,而不是串行版本的30秒
p.S.也想出了一个替代方案,我觉得这更自然。希望代码是不言自明的:
final Observable<Boolean> res = Observable.combineLatest(
a.startWith((Boolean)null),
b.startWith((Boolean)null),
c.startWith((Boolean)null),
(Boolean b1, Boolean b2, Boolean b3) -> {
// note that b1/b2/b3 might be null
// we interpret that as 'unfinished' computation
if (Boolean.TRUE.equals(b1) || Boolean.TRUE.equals(b2) || Boolean.TRUE.equals(b3)) {
// if any of source observables has finished and was true, the result is obviously true
return true; }
if (Boolean.FALSE.equals(b1) && Boolean.FALSE.equals(b2) && Boolean.FALSE.equals(b3)) {
// if all of source observables have finished and are false, the result is false
return false;
}
return null; // otherwise we're in some kind of intermediate state
}
)
.filter(item -> item != null)
.first();
final Observable res=Observable.combinelatetest(
a、 startWith((布尔)null),
b、 startWith((布尔)null),
c、 startWith((布尔)null),
(布尔b1、布尔b2、布尔b3)->{
//请注意,b1/b2/b3可能为空
//我们将其解释为“未完成”计算
if(Boolean.TRUE.equals(b1)| Boolean.TRUE.equals(b2)| Boolean.TRUE.equals(b3)){
//如果任何源观测值已经完成并且为真,那么结果显然是真的
返回true;}
if(Boolean.FALSE.equals(b1)&&Boolean.FALSE.equals(b2)&&Boolean.FALSE.equals(b3)){
//如果所有源观测都已完成且为假,则结果为假
返回false;
}
返回null;//否则我们处于某种中间状态
}
)
.filter(项目->项目!=null)
.first();
嗯。。。这个怎么样:
return Observable.concatMap(
a.meetsCriteria(),
b.meetsCriteria(),
c.meetsCriteria())
.filter(value -> value)
.takeFirst();
这是一个很好的谜题,谢谢:)要避免一个接一个地执行,您需要连续调用它们。因此,试图将它们组合成一个可观察的对象,而不是简单地使用一个捷径
|
,这一点并不清楚。
return Observable.concatMap(
a.meetsCriteria(),
b.meetsCriteria(),
c.meetsCriteria())
.filter(value -> value)
.takeFirst();