Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 当组合多个观测值时,如何急切地返回RxJava?_Android_Rx Java - Fatal编程技术网

Android 当组合多个观测值时,如何急切地返回RxJava?

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,

假设我有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, 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
    out
    true
    它们中任何一个发出的值
  • 使用
    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();