RxJava 是一個基于觀察者模式的響應式編程庫,在 Android 開發中被廣泛使用。其中,過濾和條件操作是 RxJava 中非常重要的一部分,它們允許我們對數據流進行精細控制。本文將詳細介紹 RxJava 中常用的過濾與條件操作符及其使用場景。
一、過濾操作符
1. filter()
filter()
?是最基本的過濾操作符,它根據給定的條件過濾發射的數據項。
java
Observable.just(1, 2, 3, 4, 5).filter(number -> number % 2 == 0).subscribe(evenNumber -> Log.d("TAG", "Even number: " + evenNumber)); // 輸出: Even number: 2, Even number: 4
2. take()
take()
?只發射前 N 項數據,然后取消訂閱。
java
Observable.just(1, 2, 3, 4, 5).take(3).subscribe(number -> Log.d("TAG", "Number: " + number)); // 輸出: Number: 1, Number: 2, Number: 3
3. takeLast()
takeLast()
?只發射最后 N 項數據。
java
Observable.just(1, 2, 3, 4, 5).takeLast(2).subscribe(number -> Log.d("TAG", "Number: " + number)); // 輸出: Number: 4, Number: 5
4. skip()
skip()
?跳過前 N 項數據,發射剩余的數據。
java
Observable.just(1, 2, 3, 4, 5).skip(2).subscribe(number -> Log.d("TAG", "Number: " + number)); // 輸出: Number: 3, Number: 4, Number: 5
5. skipLast()
skipLast()
?跳過后 N 項數據,發射前面的數據。
java
Observable.just(1, 2, 3, 4, 5).skipLast(2).subscribe(number -> Log.d("TAG", "Number: " + number)); // 輸出: Number: 1, Number: 2, Number: 3
6. distinct()
distinct()
?過濾掉重復的數據項。
java
Observable.just(1, 2, 2, 3, 4, 4, 5).distinct().subscribe(number -> Log.d("TAG", "Number: " + number)); // 輸出: Number: 1, Number: 2, Number: 3, Number: 4, Number: 5
7. distinctUntilChanged()
distinctUntilChanged()
?過濾掉連續重復的數據項。
java
Observable.just(1, 2, 2, 3, 2, 4, 4, 5).distinctUntilChanged().subscribe(number -> Log.d("TAG", "Number: " + number)); // 輸出: Number: 1, Number: 2, Number: 3, Number: 2, Number: 4, Number: 5
8. elementAt()
elementAt()
?只發射指定索引位置的數據項。
java
Observable.just(1, 2, 3, 4, 5).elementAt(2).subscribe(number -> Log.d("TAG", "Number: " + number)); // 輸出: Number: 3
9. ignoreElements()
ignoreElements()
?忽略所有數據項,只發射完成或錯誤通知。
java
Observable.just(1, 2, 3, 4, 5).ignoreElements().subscribe(() -> Log.d("TAG", "Completed"),throwable -> Log.e("TAG", "Error", throwable)); // 輸出: Completed
10. debounce()
debounce()
?僅在特定時間段內沒有發射其他數據時才發射數據,常用于搜索輸入框。
java
RxTextView.textChanges(searchEditText).debounce(300, TimeUnit.MILLISECONDS).subscribe(charSequence -> performSearch(charSequence.toString()));
11. throttleFirst()
throttleFirst()
?在指定時間窗口內只發射第一個數據項,常用于防止按鈕重復點擊。
java
RxView.clicks(button).throttleFirst(1, TimeUnit.SECONDS).subscribe(aVoid -> performAction());
12. throttleLast() / sample()
throttleLast()
?或?sample()
?在指定時間窗口內只發射最后一個數據項。
java
Observable.interval(100, TimeUnit.MILLISECONDS).throttleLast(1, TimeUnit.SECONDS).subscribe(number -> Log.d("TAG", "Number: " + number)); // 每秒發射一個數字
二、條件操作符
1. all()
all()
?判斷是否所有數據項都滿足某個條件。
java
Observable.just(2, 4, 6, 8).all(number -> number % 2 == 0).subscribe(isAllEven -> Log.d("TAG", "All even? " + isAllEven)); // 輸出: All even? true
2. contains()
contains()
?判斷數據流是否包含某個特定項。
java
Observable.just(1, 2, 3, 4, 5).contains(3).subscribe(contains -> Log.d("TAG", "Contains 3? " + contains)); // 輸出: Contains 3? true
3. isEmpty()
isEmpty()
?判斷數據流是否為空。
java
Observable.empty().isEmpty().subscribe(isEmpty -> Log.d("TAG", "Is empty? " + isEmpty)); // 輸出: Is empty? true
4. defaultIfEmpty()
defaultIfEmpty()
?如果數據流為空,則發射一個默認值。
java
Observable.empty().defaultIfEmpty("Default Value").subscribe(value -> Log.d("TAG", "Value: " + value)); // 輸出: Value: Default Value
5. sequenceEqual()
sequenceEqual()
?比較兩個 Observable 發射的數據序列是否相同。
java
Observable.sequenceEqual(Observable.just(1, 2, 3),Observable.just(1, 2, 3) ).subscribe(isEqual -> Log.d("TAG", "Sequences equal? " + isEqual)); // 輸出: Sequences equal? true
6. amb()
amb()
?從多個 Observable 中選擇第一個發射數據的 Observable。
java
Observable.amb(Observable.just(1, 2, 3).delay(1, TimeUnit.SECONDS),Observable.just(4, 5, 6) ).subscribe(number -> Log.d("TAG", "Number: " + number)); // 輸出: Number: 4, Number: 5, Number: 6
三、實際應用場景
1. 搜索功能優化
java
RxTextView.textChanges(searchEditText).debounce(300, TimeUnit.MILLISECONDS) // 防抖.filter(text -> text.length() > 2) // 至少3個字符才搜索.distinctUntilChanged() // 內容變化才搜索.switchMap(query -> searchApi(query)) // 取消之前的搜索.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(results -> updateUI(results));
2. 防止按鈕重復點擊
java
RxView.clicks(button).throttleFirst(1, TimeUnit.SECONDS) // 1秒內只響應第一次點擊.subscribe(aVoid -> performAction());
3. 數據校驗
java
Observable.just(userInput).filter(input -> !TextUtils.isEmpty(input)).map(input -> Integer.parseInt(input)).filter(number -> number > 0 && number < 100).subscribe(validNumber -> processInput(validNumber));
四、總結
RxJava 的過濾和條件操作符為 Android 開發提供了強大的數據流控制能力。合理使用這些操作符可以:
減少不必要的處理,提高性能
簡化代碼邏輯,提高可讀性
處理復雜的異步場景
優化用戶體驗
掌握這些操作符是成為 RxJava 高手的必經之路。建議在實際開發中多練習,理解每個操作符的特性和適用場景,從而寫出更優雅、高效的響應式代碼。