RxJava 學習筆記 -- 過濾操作符

小碼農沐楓發表於2018-09-12

RxJava 基礎知識

image

RxJava 學習筆記 -- 過濾操作符

image

操作符作用
filter()過濾資料
takeLast()只發射最後的N項資料
last()只發射最後一項資料
lastOrDefault()只發射最後一項資料,如果Observable為空,將發射預設值
takeLastBuffer()將最後的N項資料當做單個資料發射
skip()跳過開始的N項資料
skipLast()跳過最後的N項資料
take()只發射開始的N項資料
first() and takeFirst()只發射第一項資料,或者滿足某種條件的第一項資料
firstOrDefault()只發射第一項資料,如果Observable為空,就發射預設值
elementAt()發射第N項資料
elementAtOrDefault()發射第N項資料,如果Observable資料少於N項,就發射預設值
sample() or throttleLast()定期發射Observable最近的資料
throttleFirst()定期發射Observable發射的第一項資料
throttleWithTimeout() or debounce()只有當Observable在指定的時間段後還沒有發射資料時,才發射一個資料
timeout()如果在一個指定的時間段後還沒有發射資料,就發射一個異常
distinct()過濾掉重複的資料
distinctUntilChanged()過濾掉連續重複的資料
ofType()只發射指定型別的資料
ignoreElements()丟棄所有的正常資料,只發射錯誤或完成通知

下面只列舉一些常用的過濾操作符的用法

一. First操作符

只發射第一項(或滿足某個條件的第一項)資料, 如圖: image

在RxJava2.x 中,使用first()需要一個預設的Item,對於Observable而言,使用了first()會返回Single型別

fun testFirst(){
            Observable.just(1,2,3,4)
                    .first(2)
                    .subscribeBy(
                            onSuccess = {Log.e("TAG",it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)}
                    )

            // Observable 不發射任何資料,那麼first操作符的預設值就起作用了
            Observable.empty<Int>()
                    .first(2)
                    .subscribeBy(
                            onSuccess = {Log.e("TAG","顯示預設值: "+it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)}
                    )
        }
複製程式碼

執行結果

09-10 15:33:55.120 12372-12372/com.mufeng.rxjavademo E/TAG: 1
09-10 15:33:55.122 12372-12372/com.mufeng.rxjavademo E/TAG: 顯示預設值: 2
複製程式碼

二. Last操作符

只發射最後一項(或者滿足某個條件的最後一項)資料, 如圖:

image

last操作符和first操作符類似,需要一個預設的Item, 也是返回Single型別

fun testLast(){

            Observable.just(1,2,3,4)
                    .last(3)
                    .subscribeBy(
                            onSuccess = {Log.e("TAG",it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)}
                    )
            // Observable 不發射任何資料,那麼last操作符的預設值就起作用了
            Observable.empty<Int>()
                    .last(2)
                    .subscribeBy(
                            onSuccess = {Log.e("TAG","顯示預設值: "+it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)}
                    )
        }
複製程式碼

執行結果

09-10 15:41:45.703 12628-12628/com.mufeng.rxjavademo E/TAG: 4
09-10 15:41:45.705 12628-12628/com.mufeng.rxjavademo E/TAG: 顯示預設值: 2
複製程式碼

三. Task操作符

只發射前面的n項資料, 如圖:

image

簡單用法

fun testTake(){
            Observable.just(1,2,3,4,5)
                    .take(3)
                    .subscribeBy(
                            onNext = {Log.e("TAG",it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)},
                            onComplete = {Log.e("TAG","onComplete")}
                    )
        }
複製程式碼

執行結果

09-11 14:50:04.946 13005-13005/com.mufeng.rxjavademo E/TAG: 1
    2
09-11 14:50:04.947 13005-13005/com.mufeng.rxjavademo E/TAG: 3
    onComplete
複製程式碼

如果Observable發射的資料少於N項,take操作符生成的Observable不會丟擲異常或發射onError通知,仍然會發射出這些資料

示例:

fun testTake(){
            Observable.just(1,2,3,4,5)
                    .take(7)
                    .subscribeBy(
                            onNext = {Log.e("TAG",it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)},
                            onComplete = {Log.e("TAG","onComplete")}
                    )
        }
複製程式碼

執行結果

09-11 14:53:17.308 13172-13172/com.mufeng.rxjavademo E/TAG: 1
09-11 14:53:17.309 13172-13172/com.mufeng.rxjavademo E/TAG: 2
    3
    4
    5
    onComplete

複製程式碼

四. TakeLast操作符

發射Observable發射的最後N項資料

image

fun testTakeLast(){
            Observable.just(1,2,3,4,5,6)
                    .takeLast(3)
                    .subscribeBy(
                            onNext = {Log.e("TAG",it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)},
                            onComplete = {Log.e("TAG","onComplete")}
                    )
        }
複製程式碼

執行結果

09-11 15:02:47.704 13403-13403/com.mufeng.rxjavademo E/TAG: 4
09-11 15:02:47.705 13403-13403/com.mufeng.rxjavademo E/TAG: 5
    6
    onComplete

複製程式碼

五. Skip

使用skip操作符,可以忽略Observable發射的前N項資料,只保留之後的資料

image

fun testSkip(){
            Observable.just(1,2,3,4,5,6)
                    .skip(3)
                    .subscribeBy(
                            onNext = {Log.e("TAG",it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)},
                            onComplete = {Log.e("TAG","onComplete")}
                    )
        }
複製程式碼

執行結果

09-11 15:07:06.011 13625-13625/com.mufeng.rxjavademo E/TAG: 4
    5
    6
    onComplete

複製程式碼

六. SkipLast

使用skipLast操作符,可以忽略Observable發射的後N項資料,只發射前面的資料

image

fun testSkipLast(){
            Observable.just(1,2,3,4,5,6)
                    .skipLast(3)
                    .subscribeBy(
                            onNext = {Log.e("TAG",it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)},
                            onComplete = {Log.e("TAG","onComplete")}
                    )
        }
複製程式碼

執行結果

09-11 15:12:57.617 13827-13827/com.mufeng.rxjavademo E/TAG: 1
    2
    3
    onComplete
複製程式碼

七. elementAt

elementAt操作符獲取原始Observable發射的資料序列指定索引位置的資料項,然後當做自己的唯一資料發射

它傳遞一個以0為起始的索引值,發射原始Observable資料序列對應索引位置的值,如果傳遞的值大於原始Observable發射的資料數量,會直接傳送onComplete事件,如果傳遞的是一個負數,則會丟擲"java.lang.IndexOutOfBoundsException: index >= 0 required but it was -1"異常

fun testElementAt(){
            Observable.just(1,2,3,4,5,6)
                    .elementAt(-1)
                    .subscribeBy(
                            onSuccess = {Log.e("TAG",it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)},
                            onComplete = {Log.e("TAG","onComplete")}
                    )
        }
複製程式碼

執行結果

09-11 15:21:00.009 14074-14074/com.mufeng.rxjavademo E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.mufeng.rxjavademo, PID: 14074
    java.lang.IndexOutOfBoundsException: index >= 0 required but it was -1
        at io.reactivex.Observable.elementAt(Observable.java:8105)
        ...
複製程式碼

八. ignoreElements

ignoreElements操作符忽略原始Observable發射的所有資料,只允許它的終止通知通過,它返回一個Completable型別

image

九. distinct

distinct 的過濾規則是,只允許沒有發射過的資料項通過

fun testDistince(){
            Observable.just(1,2,1,2,3,1)
                    .distinct()
                    .subscribeBy(
                            onNext = {Log.e("TAG",it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)},
                            onComplete = {Log.e("TAG","onComplete")}
                    )
        }
複製程式碼

執行結果

09-11 15:48:30.881 14799-14799/com.mufeng.rxjavademo E/TAG: 1
    2
    3
    onComplete

複製程式碼

distinct還能接受一個Function作為引數,這個函式根據原始Observable發射的資料產生一個key,然後比較這些key而不是資料本身,來判定兩個資料是否不同

與distinct類似的是distinctUntilChanged操作符,該操作符與distinct的區別是,它只判斷一個資料與它的前面的一個相鄰的資料是否不同

十. filter

filter操作符使用你指定的一個謂詞函式測試資料項,只有通過測試的資料才會被髮射

fun testFilter(){
            Observable.just(1,2,3,4,5,6)
                    .filter{it > 3}
                    .subscribeBy(
                            onNext = {Log.e("TAG",it.toString())},
                            onError = {Log.e("TAG",it.localizedMessage)},
                            onComplete = {Log.e("TAG","onComplete")}
                    )
        }
複製程式碼

執行結果

09-11 15:56:16.980 15032-15032/com.mufeng.rxjavademo E/TAG: 4
09-11 15:56:16.981 15032-15032/com.mufeng.rxjavademo E/TAG: 5
    6
    onComplete

複製程式碼

十一. throttleFirst

值得一提的是throttleFirst操作符,配合RxBinding使用,可以有效的限制重複點選事件





相關文章