如何使用RxJava的值

时间:2017-12-14 19:02:08

标签: rx-java2

我正在用这样的rxjava2制作一系列事件。

Observable<Integer> observable = booleanPublisher.map(aBoolean -> {
        if(aBoolean){
            return 1;
        }else{
            return 0;
        }
    }).buffer(4).map( aLilst ->{
        int sum = 0;
        for (Integer i: aLilst) {
            sum +=i;
        }
        return sum;
    });
    observable.subscribe(
            aInt ->{
                Log.v("Value",String.valueOf(aInt));
            }
    );

这会产生一个int事件流,其值为0..4,现在我想过滤这个事件,当例如一行中的2个整数事件小于4时发出一个事件,而另一个事件是连续10个具有4个值的整数事件。我试图将两个不同的可观察量分开并合并,但没有运气,因为这两个事件必须互相重置。

提前致谢。

2 个答案:

答案 0 :(得分:1)

避免使用两种不同订阅的另一个选择是使用merge,这样:

enum MatchResult{
    TWO_ITEM_SMALL,
    FIVE_CONSECUTIVE
}


Observable<MatchResult> getObservable1(Observable<Integer> observable) {
        return observable
                .scan(0, (integer, integer2) -> {
                    if (integer2 < 4) {
                        return integer + 1;
                    }
                    return 0;
                }).filter(integer -> integer >= 2)
                .map(integer -> MatchResult.TWO_ITEM_SMALL);
    }

Observable<MatchResult> getObservable2(Observable<Integer> observable) {
    return observable
            .scan(0, (integer, integer2) -> {
                if (integer2 == 4) {
                    return integer + 1;
                } else {
                    return 0;
                }
            }).filter(integer -> integer >= 5)
            .map(integer -> MatchResult.FIVE_CONSECUTIVE);
    }


Observable.merge(getObservable1(getSoruce()), getObservable2(getSoruce()))
            .subscribe(matchResult -> {
                if(matchResult == MatchResult.TWO_ITEM_SMALL) {
                    logd("two items in a row, smaller than 4.");
                } else {
                    logd("five items in a row equals to 4");
                }
            });

答案 1 :(得分:0)

实现它的一种方法是使用scan运算符。正如文档所说:

  

“扫描”操作符将函数应用于由此发出的第一个项目   source Observable然后以该函数的形式发出该函数的结果   自己的第一次排放。

作为函数的返回值,您可以获得符合条件的行中的项目数。

我认为在单个订阅中有一种方法可以实现,但我认为通过ConnectableObservable运算符使用publish()将其拆分更为清晰。让我们举个例子:

Observable<Integer> getSource() {
    return Observable.just(1, 2, 3, 4, 4, 4, 4, 4, 2);
}

现在我们创建一个观察者来检查两个连续的小于4个项目。

Observable<Integer> source = getSource();

source.scan(0, (integer, integer2) -> {
    if (integer2 < 4) {
        return integer + 1;
    }
    return 0;
    }).filter(integer -> integer >= 2)
    .subscribe(integer -> logd("two items in a row, smaller than 4."));

接收五个(为了简化)连续值的事件的订阅者等于4。

source.scan(0, (integer, integer2) -> {
    if (integer2 == 4) {
        return integer + 1;
    }
    return 0;
    }).filter(integer -> integer >= 5) // for you it will be ten
    .subscribe(integer -> logd("five items in a row equals to 4."));

现在你打电话:

observable.connect();

注意:当条件匹配时,当前实现不会重置计数器。这意味着,例如,如果您正在寻找一个包含五个连续值的序列,则该序列等于4:

4 4 4 4 4 4

将生成两个匹配,因为第一个匹配是序列的前五个项目,但是当您收到值为4的新项目时,您仍然匹配。