RxJava操作符(七)Conditional and Boolean
在這篇文章裡我們來了解一下條件和布爾操作符。
一、All/Amb
All操作符根據一個函數對源Observable發射的所有數據進行判斷,最終返回的結果就是這個判斷結果。這個函數使用發射的數據作為參數,內部判斷所有的數據是否滿足我們定義好的判斷條件,如果全部都滿足則返回true,否則就返回false。
Amb操作符可以將至多9個Observable結合起來,讓他們競爭。哪個Observable首先發射了數據(包括onError和onComplete)就會繼續發射這個Observable的數據,其他的Observable所發射的數據都會別丟棄。
下面使用這兩個操作符,對於all操作符我們做了這樣的限制,初次使用的時候tag為false,會創建6個數字的Observable,以後都會創建5個數字的Observable。
- private Observable<Boolean> allObserver() {
- Observable<Integer> just;
- if (tag) {
- just = Observable.just(1, 2, 3, 4, 5);
- } else {
- just = Observable.just(1, 2, 3, 4, 5, 6);
- }
- tag = true;
- return just.all(integer -> integer < 6);
- }
- private Observable<Integer> ambObserver() {
- Observable<Integer> delay3 = Observable.just(1, 2, 3).delay(3000, TimeUnit.MILLISECONDS);
- Observable<Integer> delay2 = Observable.just(4, 5, 6).delay(2000, TimeUnit.MILLISECONDS);
- Observable<Integer> delay1 = Observable.just(7, 8, 9).delay(1000, TimeUnit.MILLISECONDS);
- return Observable.amb(delay1, delay2, delay3);
- }
分別進訂閱
- mLButton.setText("all");
- mLButton.setOnClickListener(e -> allObserver().subscribe(i -> log("all:" + i)));
- mRButton.setText("amb");
- mRButton.setOnClickListener(e -> ambObserver().subscribe(i -> log("amb:" + i)));
運行結果如下所示。第一次返回的6個數據的Observable不滿足所有都小於6的條件,所以結果是false,以後的都滿足條件,所以結果是true。使用amb操作符的Observable,第一個發射的數據的是7,所以輸出了7,8,9,其他的數據都丟棄了。
二、Contains、IsEmpty
Contains操作符用來判斷源Observable所發射的數據是否包含某一個數據,如果包含會返回true,如果源Observable已經結束了卻還沒有發射這個數據則返回false。
IsEmpty操作符用來判斷源Observable是否發射過數據,如果發射過就會返回false,如果源Observable已經結束了卻還沒有發射這個數據則返回true。
用這兩個操作符來判斷一下兩個Observable對象是否包含某個數據及是否為空
- private Observable<Boolean> containsObserver() {
- if (tag) {
- return Observable.just(1, 2, 3).contains(3);
- }
- tag = true;
- return Observable.just(1, 2, 3).contains(4);
- }
- private Observable<Boolean> defaultObserver() {
- return Observable.create(new Observable.OnSubscribe<Integer>() {
- @Override
- public void call(Subscriber<? super Integer> subscriber) {
- subscriber.onCompleted();
- }
- }).isEmpty();
- }
分別進行訂閱
- mLButton.setText("contains");
- mLButton.setOnClickListener(e -> containsObserver().subscribe(i -> log("contains:" + i)));
- mRButton.setText("isEmpty");
- mRButton.setOnClickListener(e -> defaultObserver().subscribe(i -> log("isEmpty:" + i)));
運行結果如下
三、DefaultIfEmpty
DefaultIfEmpty操作符會判斷源Observable是否發射數據,如果源Observable發射了數據則正常發射這些數據,如果沒有則發射一個默認的數據
下面我們用這個操作符來處理一個空的和一個非空的Observable,如果為空的話就返回默認值10
- private Observable<Integer> emptyObserver() {
- return Observable.create(new Observable.OnSubscribe<Integer>() {
- @Override
- public void call(Subscriber<? super Integer> subscriber) {
- subscriber.onCompleted();
- }
- }).defaultIfEmpty(10);
- }
- private Observable<Integer> notEmptyObserver() {
- return Observable.create(new Observable.OnSubscribe<Integer>() {
- @Override
- public void call(Subscriber<? super Integer> subscriber) {
- subscriber.onNext(1);
- subscriber.onCompleted();
- }
- }).defaultIfEmpty(10);
- }
分別進行訂閱
- mLButton.setText("empty");
- mLButton.setOnClickListener(e -> emptyObserver().subscribe(i -> log("empty:" + i)));
- mRButton.setText("notEmpty");
- mRButton.setOnClickListener(e -> notEmptyObserver().subscribe(i -> log("notEmpty:" + i)));
運行結果如下
四、SequenceEqual
SequenceEqual操作符用來判斷兩個Observable發射的數據序列是否相同(發射的數據相同,數據的序列相同,結束的狀態相同),如果相同返回true,否則返回false
下面用SequenceEqual分別來判斷兩個相同的和不相同的Observable
- private Observable<Boolean> equalObserver() {
- return Observable.sequenceEqual(Observable.just(1, 2, 3), Observable.just(1, 2, 3));
- }
- private Observable<Boolean> notEqualObserver() {
- return Observable.sequenceEqual(Observable.just(1, 2, 3), Observable.just(1, 2));
- }
分別進行訂閱
- mLButton.setText("equal");
- mLButton.setOnClickListener(e -> equalObserver().subscribe(i -> log("equal:" + i)));
- mRButton.setText("notequal");
- mRButton.setOnClickListener(e -> notEqualObserver().subscribe(i -> log("notequal:" + i)));
運行結果如下
五、SkipUntil、SkipWhile
這兩個操作符都是根據條件來跳過一些數據,不同之處在於SkipUnitl是根據一個標志Observable來判斷的,當這個標志Observable沒有發射數據的時候,所有源Observable發射的數據都會被跳過;當標志Observable發射了一個數據,則開始正常地發射數據。SkipWhile則是根據一個函數來判斷是否跳過數據,當函數返回值為true的時候則一直跳過源Observable發射的數據;當函數返回false的時候則開始正常發射數據。
下面使用這兩個操作符來跳過一些數據項。
- private Observable<Long> skipUntilObserver() {
- return Observable.interval(1, TimeUnit.SECONDS).skipUntil(Observable.timer(3, TimeUnit.SECONDS));
- }
- private Observable<Long> skipWhileObserver() {
- return Observable.interval(1, TimeUnit.SECONDS).skipWhile(aLong -> aLong < 5);
- }
分別進行訂閱
- mLButton.setText("skipUntil");
- mLButton.setOnClickListener(e -> skipUntilObserver().subscribe(i -> log("skipUntil:" + i)));
- mRButton.setText("skipWhile");
- mRButton.setOnClickListener(e -> skipWhileObserver().subscribe(i -> log("skipWhile:" + i)));
運行結果如下
六、TakeUntil、TakeWhile
TakeUntil和TakeWhile操作符可以說和SkipUnitl和SkipWhile操作符是完全相反的功能。TakeUntil也是使用一個標志Observable是否發射數據來判斷,當標志Observable沒有發射數據時,正常發射數據,而一旦標志Observable發射過了數據則後面的數據都會被丟棄。TakeWhile則是根據一個函數來判斷是否發射數據,當函數返回值為true的時候正常發射數據;當函數返回false的時候丟棄所有後面的數據。
下面使用這兩個操作符來take兩個Observable發射的數據
- private Observable<Long> takeUntilObserver() {
- return Observable.interval(1, TimeUnit.SECONDS).takeUntil(Observable.timer(3, TimeUnit.SECONDS));
- }
- private Observable<Long> takeWhileObserver() {
- return Observable.interval(1, TimeUnit.SECONDS).takeWhile(aLong -> aLong < 5);
- }
分別進行訂閱
- mLButton.setText("takeUntil");
- mLButton.setOnClickListener(e -> takeUntilObserver().subscribe(i -> log("takeUntil:" + i)));
- mRButton.setText("takeWhile");
- mRButton.setOnClickListener(e -> takeWhileObserver().subscribe(i -> log("takeWhile:" + i)));
運行結果如下
關於條件和布爾操作符就到這了,本文中所有的demo程序見:https://github.com/Chaoba/RxJavaDemo