RxJava 過濾操作符

ReactiveX 系列文章目錄


blockingFirst/blockingLast

阻塞直到返回第一個/最后一個才發(fā)射數(shù)據(jù)。

Log.e("RX", "first ${Observable.just(1,2,3,4).blockingFirst()}")
// Observable 沒發(fā)射,返回默認(rèn)值
Log.e("RX", "first default ${Observable.empty<Int>().blockingFirst(10)}")
Log.e("RX", "last ${Observable.just(1,2,3,4).blockingLast()}")
Log.e("RX", "last default ${Observable.empty<Int>().blockingLast(10)}")

結(jié)果

first 1
first default 10
last 4
last default 4

現(xiàn)在想到的應(yīng)用場景也許是某些 Callable 返回的數(shù)據(jù)之類,先過濾拿到第一個,然后再用 Observable 發(fā)射這第一個數(shù)。

blockingSingle

val ob = Observable.just(1)
val i = ob.blockingSingle()
Log.e("RX", "$i")

如果發(fā)射數(shù)據(jù)只有一個,返回這個發(fā)射的值;如果多于一個,拋出異常;如果沒有發(fā)射數(shù)據(jù),返回參數(shù)傳遞的默認(rèn)值。

distinct

public final Observable<T> distinct()
public final <K> Observable<T> distinct(Function<? super T, K> keySelector)
public final <K> Observable<T> distinct(Function<? super T, K> keySelector, Callable<? extends Collection<? super K>> collectionSupplier)

去掉發(fā)射的重復(fù)數(shù)據(jù)。

val ob = Observable.fromArray(1,2,3,2,2,3,3,4,5,6,6,6,9)

// 默認(rèn)規(guī)則去重,收到 1,2,3,4,5,6,9
ob.distinct().subscribe(observerInt)

// 求余 3 后比較,4 認(rèn)為和 1 重復(fù),5 認(rèn)為和 2 重復(fù),最終只收到 1,2,3
ob.distinct { it % 3 }.subscribe(observerInt)

最后一個構(gòu)造方法,第三個參數(shù)提供一個集合,看源碼是先通過前面的 keySelector 方法獲取轉(zhuǎn)換后的數(shù)據(jù),然后往集合里面 add 要轉(zhuǎn)換后的數(shù)據(jù),只有這個 add 返回 true,才會通過 onNext 發(fā)射數(shù)據(jù)。而沒有這個參數(shù)的方法,內(nèi)部都是用的 HashSet,不許添加重復(fù)元素,這樣前面的規(guī)則判斷出哪些是重復(fù),然后這里添加。

現(xiàn)在我寫一個沒什么意義的 Collection

class MyCollection<Int>: ArrayList<Int>() {
    override fun add(element: Int): Boolean {
        super.add(element)
        return (element == 6 || element == 9 || element == 3)
    }
}

就是說只要這個值是 3,6,9 中的一個,add 方法就返回 true,其余值一律 false

// 收到 3,3,3,6,6,6,9
ob.distinct ({ it }, {MyCollection<Int>()}).subscribe(observerInt)

雖然根據(jù)默認(rèn)規(guī)則,多個 6 是相同的,但是往集合 add 返回值是 true,所以仍然發(fā)射出來,所以有多個 6。

// 只收到 onComplete
ob.distinct ({ it % 3 }, {MyCollection<Int>()}).subscribe(observerInt)

因?yàn)橐?guī)則是 it % 3,所以大于 3 的數(shù)經(jīng)轉(zhuǎn)換全部變成了 0,1,2,然后 add 返回值全部 false,所以一個都沒有發(fā)射出來。

distinctUntilChanged

public final Observable<T> distinctUntilChanged()
public final <K> Observable<T> distinctUntilChanged(Function<? super T, K> keySelector)
public final Observable<T> distinctUntilChanged(BiPredicate<? super T, ? super T> comparer)

去除相鄰的重復(fù)數(shù)據(jù)。也是通過一個 keySelector 來對數(shù)據(jù)做相應(yīng)轉(zhuǎn)換,然后通過 BiPredicate 對象 compare 來判斷兩個數(shù)據(jù)是否相等。

val ob = Observable.fromArray(1,2,3,2,2,3,3,4,5,6,6,6,9)
// 收到 1,2,3,2,3,4,5,6,9
//            ob.distinctUntilChanged().subscribe(observerInt)
// 都先轉(zhuǎn)成了 1,然后用默認(rèn)的 equals 判斷,所有都相等,所以只收到 1
//            ob.distinctUntilChanged( Function<Int, Int> { 1 } ).subscribe(observerInt)
// 雖然數(shù)據(jù)沒轉(zhuǎn)換,但判斷是否相等時都認(rèn)為是一樣的,所以也只收到 1
ob.distinctUntilChanged({ _, _ -> true}).subscribe(observerInt)

elementAt/elementAtOrError/firstElement/first/firstOrError/lastElement/last/lastOrError

只發(fā)射指定位置的數(shù)據(jù)。返回 Maybe。

// 越界,則發(fā)射 onComplete,否則發(fā)射指定 index 的數(shù)據(jù)
public final Maybe<T> elementAt(long index)
// 越界,用默認(rèn)值 defaultItem
public final Single<T> elementAt(long index, T defaultItem)
// 越界,拋出異常
public final Single<T> elementAtOrError(long index)

public final Maybe<T> firstElement() {
    return elementAt(0L);
}
public final Single<T> first(T defaultItem) {
    return elementAt(0L, defaultItem);
}
public final Single<T> firstOrError() {
    return elementAtOrError(0L);
}

// 空,發(fā)射 onComplete
public final Maybe<T> lastElement()
// 空,用默認(rèn)值
public final Single<T> last(T defaultItem)
// 空,拋出異常
public final Single<T> lastOrError()
Observable.just(1, 2, 3, 4).elementAt(2)
            .subscribe({ textView.text = "${textView.text}\n $it" })

Observable.just(1, 2, 3, 4).elementAt(6, 0)
                  .subscribe(Consumer<Int> { textView.text = "${textView.text}\n $it" })

Observable.just(1, 2, 3, 4).elementAtOrError(6)
                   .subscribe(Consumer<Int> { textView.text = "${textView.text}\n $it" })

filter

過濾。

Observable.just(1,2,3,4,5,6)
     .filter({ it % 2 == 0 }).subscribe(observerInt)

filter 的參數(shù)是 Predicate,test 方法用于過濾,返回 false 的丟棄。

public interface Predicate<T> {
    /**
     * Test the given input value and return a boolean.
     * @param t the value
     * @return the boolean result
     * @throws Exception on error
     */
    boolean test(@NonNull T t) throws Exception;
}

ofType

內(nèi)部調(diào)用 filter,過濾指定的 Class 類型的數(shù)據(jù)。

// 只收到 a 和 b
Observable.just(1,2,"a","b", 4L, true)
                                .ofType(String::class.java).subscribe { t-> textView.text = "${textView.text}\n $t"}

ignoreElements

忽略所有數(shù)據(jù),只接受 complete 或 error 事件。

Observable.range(0, 5)
        .ignoreElements().subscribe(object : Action {
            override fun run() {
                textView.text = "${textView.text}\n complete"
            }
        }, object : Consumer<Throwable> {
            override fun accept(t: Throwable?) {
                textView.text = "${textView.text}\n error"
            }
        })

singleElement

val observer = object : MaybeObserver<Int> {
        override fun onSuccess(t: Int) { Log.e("RX", "onSuccess $t") }
        override fun onComplete() { Log.e("RX", "onComplete") }
        override fun onSubscribe(d: Disposable) {}
        override fun onError(e: Throwable) {}
}

// 因?yàn)榘l(fā)射了兩個數(shù),所以什么都收不到
// val observable = Observable.just(1,2)
// onSuccess 1
// val observable = Observable.just(1)
// onComplete
val observable = Observable.empty<Int>()

observable.singleElement().subscribe(observer)

single/singleOrError

val observer = object : SingleObserver<Int> {
    override fun onSuccess(t: Int) { Log.e("RX", "onSuccess $t") }
    override fun onSubscribe(d: Disposable) {}
    override fun onError(e: Throwable) {Log.e("RX", "onError ${e.message}")}
}
// 超過一個,拋異常,進(jìn) onError
// val observable = Observable.just(1,2)
// onSuccess 1
// val observable = Observable.just(1)
// 發(fā)射數(shù)據(jù)為空,使用默認(rèn)值,onSuccess 100
val observable = Observable.empty<Int>()
observable.single(100).subscribe(observer)

// 如果只發(fā)射一個值,進(jìn)入 onSuccess,否則都是 onError
observable.singleOrError().subscribe(observer)

skip/skipLast/skipUntil/skipWhile

// 跳過指定數(shù)目
public final Observable<T> skip(long count)
// 跳過指定時間
public final Observable<T> skip(long time, TimeUnit unit)
public final Observable<T> skip(long time, TimeUnit unit, Scheduler scheduler)

// 反方向跳過
public final Observable<T> skipLast(int count)
public final Observable<T> skipLast(long time, TimeUnit unit)
public final Observable<T> skipLast(long time, TimeUnit unit, boolean delayError)
public final Observable<T> skipLast(long time, TimeUnit unit, Scheduler scheduler)
public final Observable<T> skipLast(long time, TimeUnit unit, Scheduler scheduler, boolean delayError)
public final Observable<T> skipLast(long time, TimeUnit unit, Scheduler scheduler, boolean delayError, int bufferSize)

public final <U> Observable<T> skipUntil(ObservableSource<U> other)

public final Observable<T> skipWhile(Predicate<? super T> predicate)
val ob = Observable.intervalRange(0, 10, 0, 100, TimeUnit.MILLISECONDS)
val consumer  = Consumer<Long>{ Log.e("RX", "$it") }

// 收到 3-9
ob.skip(3).subscribe(consumer)
// 跳過 400ms,收到 4-9
ob.skip(400, TimeUnit.MILLISECONDS).subscribe(consumer)

// 收到 0-6
ob.skipLast(3).subscribe(consumer)

// 直到返回的 Observable 開始發(fā)射,這之前源 Observable 發(fā)射的數(shù)據(jù)跳過
// 收到 5-9
ob.skipUntil(Observable.timer(500, TimeUnit.MILLISECONDS))
            .subscribe(consumer)

// 只要條件滿足就跳過,收到 4-9
var i = 0
ob.skipWhile { i++ < 4 }.subscribe(consumer)

take/takeLast/takeUntil/takeWhile

// 最多發(fā)多少個數(shù)據(jù)
public final Observable<T> take(long count)
// 只發(fā)射某個時間間隔前的數(shù)據(jù)
public final Observable<T> take(long time, TimeUnit unit)
public final Observable<T> take(long time, TimeUnit unit, Scheduler scheduler)

// 反方向
public final Observable<T> takeLast(int count)
// 只發(fā)射在源 Observable 的 complete 之前某個間隔的數(shù)據(jù)
public final Observable<T> takeLast(long time, TimeUnit unit)
public final Observable<T> takeLast(long time, TimeUnit unit, boolean delayError)
public final Observable<T> takeLast(long time, TimeUnit unit, Scheduler scheduler)
public final Observable<T> takeLast(long time, TimeUnit unit, Scheduler scheduler, boolean delayError)
public final Observable<T> takeLast(long time, TimeUnit unit, Scheduler scheduler, boolean delayError, int bufferSize)

// 同時用時間和數(shù)目的限制
public final Observable<T> takeLast(long count, long time, TimeUnit unit)
public final Observable<T> takeLast(long count, long time, TimeUnit unit, Scheduler scheduler)
public final Observable<T> takeLast(long count, long time, TimeUnit unit, Scheduler scheduler, boolean delayError, int bufferSize)

// 當(dāng) other 發(fā)射時不再從源 Observable 中取
public final <U> Observable<T> takeUntil(ObservableSource<U> other)
// 返回 true 時停止 take,發(fā)射的數(shù)據(jù)作為參數(shù)
public final Observable<T> takeUntil(Predicate<? super T> stopPredicate)
// 條件滿足時一直 take
public final Observable<T> takeWhile(Predicate<? super T> predicate)
val ob = Observable.intervalRange(0, 10, 0, 100, TimeUnit.MILLISECONDS)
val consumer  = Consumer<Long>{ Log.e("RX", "$it") }

ob.take(3).subscribe(consumer) // 0,1,2

// complete 前 300ms 的數(shù)據(jù),即 7,8,9
ob.takeLast(300, TimeUnit.MILLISECONDS).subscribe(consumer)

// 參數(shù)的 Observable 開始發(fā)射時停止 take,收到 0,1,2
ob.takeUntil(Observable.timer(300, TimeUnit.MILLISECONDS)).subscribe(consumer)

// 發(fā)射的數(shù)據(jù)大于 3 時,停止 take,收到 0,1,2,3,4
ob.takeUntil { it > 3 }.subscribe(consumer)

// 發(fā)射的數(shù)據(jù)小于 3 時就一直 take,收到 0,1,2
ob.takeWhile { it < 3 }.subscribe(consumer)

debounce/throttleWithTimeout

public final Observable<T> debounce(long timeout, TimeUnit unit)

每產(chǎn)生一個數(shù)據(jù)后,如果在規(guī)定的間隔時間內(nèi)沒有別的數(shù)據(jù)產(chǎn)生,就會發(fā)射這個數(shù)據(jù),否則忽略該數(shù)據(jù)。

Observable.create(ObservableOnSubscribe<Int> { emitter ->
    emitter.onNext(1)
    Thread.sleep(100)
    emitter.onNext(2)
    Thread.sleep(300)
    emitter.onNext(3)
    Thread.sleep(200)
    emitter.onNext(4)
    Thread.sleep(400)
}).debounce(250, TimeUnit.MILLISECONDS)
    .subscribe({
        Log.e("RX", "$it")
    })

日志顯示 2 和 4,首先發(fā)射 1,100ms 后發(fā)射 2,也就是說發(fā)射 1 后的 250ms 以內(nèi)又發(fā)射了其它數(shù),那么忽略 1,2 發(fā)射后 250ms 內(nèi)并沒有新數(shù)據(jù)發(fā)出,因?yàn)?300ms 后才發(fā)出 3,所以接收了 2,3 發(fā)射后 200ms 發(fā)射 4,那么忽略 3,4 之后沒數(shù)據(jù)再發(fā)射,所以接收 4.

public final <U> Observable<T> debounce(Function<? super T, ? extends ObservableSource<U>> debounceSelector)
Observable.create(ObservableOnSubscribe<Int> { emitter ->
    emitter.onNext(1)
    Thread.sleep(100)
    emitter.onNext(2)
    Thread.sleep(300)
    emitter.onNext(3)
    Thread.sleep(200)
    emitter.onNext(4)
}).debounce({
    if (it == 2)
        Observable.timer(200, TimeUnit.MILLISECONDS)
    else
        Observable.timer(100, TimeUnit.MILLISECONDS)
  })
  .subscribe({
      Log.e("RX", "$it")
  })

Function 里方法返回的 Observeable,在它發(fā)射結(jié)束之前,原始 Observable 發(fā)射了新的數(shù)據(jù),舊的被忽略。比如發(fā)射 1 時,返回的這個 Observable 需要 200ms 后才結(jié)束,而 100ms 后就發(fā)射了 2,所以 1 沒了,對于 2,返回的 Observable 也要 200ms 結(jié)束,它結(jié)束后再過 100ms 才發(fā)了 3,所以 2,3 都在。

throttleWithTimeout 內(nèi)部就是直接調(diào)用了 debounce。

sample/throttleLast

定期掃描源 Observable 產(chǎn)生的結(jié)果,在指定的間隔周期內(nèi)進(jìn)行采樣。

public final Observable<T> sample(long period, TimeUnit unit)
// emitLast 是否發(fā)射最后一個數(shù)據(jù),若沒有這個參數(shù),默認(rèn)是 false
public final Observable<T> sample(long period, TimeUnit unit, boolean emitLast)
public final Observable<T> sample(long period, TimeUnit unit, Scheduler scheduler)
public final Observable<T> sample(long period, TimeUnit unit, Scheduler scheduler, boolean emitLast)
// 收到 3,6,9,12,15,18
Observable.intervalRange(1, 20, 0,100, TimeUnit.MILLISECONDS)
                         .sample(300, TimeUnit.MILLISECONDS).subscribe { Log.e("RX", "$it") }

// 收到 3,6,9,12,15,18,20
Observable.intervalRange(1, 20, 0,100, TimeUnit.MILLISECONDS)
                         .sample(300, TimeUnit.MILLISECONDS, true).subscribe { Log.e("RX", "$it") }
public final <U> Observable<T> sample(ObservableSource<U> sampler)
public final <U> Observable<T> sample(ObservableSource<U> sampler, boolean emitLast)

參數(shù)里的 Observable 發(fā)射時,從源 Observable 中取出一個發(fā)射。

// 收到 1,2,3,...,8,9
Observable.intervalRange(1, 20, 0, 100, TimeUnit.MILLISECONDS)
                .sample(Observable.intervalRange(1, 10, 0, 100, TimeUnit.MILLISECONDS))
                .subscribe { Log.e("RX", "$it") }

// 收到 2,4,6,...,16,18
Observable.intervalRange(1, 20, 0, 100, TimeUnit.MILLISECONDS)
                  .sample(Observable.intervalRange(1, 10, 200, 200, TimeUnit.MILLISECONDS))
                  .subscribe { Log.e("RX", "$it") }

// 什么都收不到
Observable.intervalRange(1, 20, 0, 100, TimeUnit.MILLISECONDS)
        .sample(Observable.just("a","b"))
        .subscribe { Log.e("RX", "$it") }

throttleLast 內(nèi)部直接就是調(diào)用 sample 方法,兩者沒有任何區(qū)別,只是它的重載方法只有兩個。

public final Observable<T> throttleLast(long intervalDuration, TimeUnit unit)
public final Observable<T> throttleLast(long intervalDuration, TimeUnit unit, Scheduler scheduler)

throttleFirst

和 throttleLast 基本一樣,throttleLast 是每次采取取最后那個,而 throttleFirst 是第一項(xiàng)。

// throttleLast 收到 3,6,9,12,15,18
// throttleFirst 收到 1,5,9,13,17
Observable.intervalRange(1, 20, 0,100, TimeUnit.MILLISECONDS)
                    .throttleFirst(300, TimeUnit.MILLISECONDS)
                    .subscribe { Log.e("RX", "$it") }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 作者: maplejaw本篇只解析標(biāo)準(zhǔn)包中的操作符。對于擴(kuò)展包,由于使用率較低,如有需求,請讀者自行查閱文檔。 創(chuàng)...
    maplejaw_閱讀 45,788評論 8 93
  • 前言 Rxjava,由于其基于事件流的鏈?zhǔn)秸{(diào)用、邏輯簡潔 & 使用簡單的特點(diǎn),深受各大 Android開發(fā)者的歡迎...
    Carson帶你學(xué)安卓閱讀 22,478評論 10 62
  • 創(chuàng)建操作 用于創(chuàng)建Observable的操作符Create通過調(diào)用觀察者的方法從頭創(chuàng)建一個ObservableEm...
    rkua閱讀 1,863評論 0 1
  • 注:只包含標(biāo)準(zhǔn)包中的操作符,用于個人學(xué)習(xí)及備忘參考博客:http://blog.csdn.net/maplejaw...
    小白要超神閱讀 2,230評論 2 8
  • 本篇文章介主要紹RxJava中操作符是以函數(shù)作為基本單位,與響應(yīng)式編程作為結(jié)合使用的,對什么是操作、操作符都有哪些...
    嘎啦果安卓獸閱讀 2,890評論 0 10