首先:
- RXJava建議先掌握Lambda, 否則要定義很多泛型. 並且程式碼量冗餘.
- RxJava分為三部分,
Observable
被觀察者 和Observer
觀察者 以及操作符. - Reactive流式程式設計是微軟提出來的概念, 由Netfix公司實現的架構.
- RxJava是針對Java語言, Android和JavaEE都可以使用, 但是目前主要是Android在使用.
- 操作符(或者直接叫方法)有很多變形(或者說方法的過載)
優點:
- 對於多執行緒任務的非同步處理非常強大和方便
- 某些自己實現很複雜的功能RxJava都提供好了
官方網站:
針對Android的擴充套件
-
主要是增加了Android中的執行緒(AndroidSchedulers)
-
實現了Android View的事件被觀察者
-
自動解綁觀察者的擴充套件元件(跟隨Activity生命週期)
-
RxJava實現的事件匯流排
文件
基本使用
排程器
public final Observable<T> subscribeOn(Scheduler scheduler)
public final Observable<T> observeOn(Scheduler scheduler)
複製程式碼
AndroidScheduler是RxAndroid新增的排程器, 主要增加了主執行緒.
- 被觀察者預設在建立例項的當前執行緒下, 觀察者(操作符)跟隨被觀察者執行緒;
- subscribeOn決定被觀察者的執行緒(只有第一次指定執行緒有效), 某些被觀察者擁有預設執行緒就無法變更(例如interval預設在computation執行緒下)
- observeOn決定以下的觀察者執行緒(包括操作符) (可以多次變更執行緒), 包括observerOn以下的無預設排程器的操作符回撥函式的執行執行緒;
操作符
- 不能指定Scheduler的操作符都是跟隨被觀察者的執行緒, 可以通過
subscribeOn
來控制被觀察者發射事件的執行緒 - 如果操作符擁有預設的執行緒排程器將無法通過subscribeOn來控制(但是一般有過載方法可以在引數中控制)
排程器型別
Schedulers.computation( )
用於計算任務,如事件迴圈或和回撥處理,不要用於io操作, 執行緒數等於處理器的數量
Schedulers.from(executor)
使用指定的Executor作為排程器
Schedulers.io( )
用於IO密集型任務,如非同步阻塞IO操作,這個排程器的執行緒池會根據需要增長;對於普通的計算任務,請使用
Schedulers.newThread( )
為每個任務建立一個新的執行緒
Schedulers.trampoline( )
在當前執行緒執行任務
Schedulers.single()
所有使用該排程器的都始終處於同一個執行緒,且任務以先進先出的順序被執行.
複製程式碼
批量解除訂閱關係
CompositeDisposable
示例:
CompositeDisposable compositeDisposable=new CompositeDisposable();
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onComplete();或者 emitter.onError(new Throwable("O__O "));
}
}).subscribe(new Observer<Integer>() {
private Disposable mDisposable;
@Override
public void onSubscribe(Disposable d) {
// 訂閱
mDisposable = d;
// 新增到容器中
compositeDisposable.add(d);
}
@Override
public void onNext(Integer value) {
// 判斷mDisposable.isDisposed() 如果解除了則不需要處理
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
// 解除所有訂閱者
compositeDisposable.clear();
複製程式碼
需要強調的是Observable只有存在訂閱者的時候才會傳送事件, 如果取消了訂閱者並不會傳送任何事件, 不用擔心記憶體洩漏等問題.
周期函式
doOn**()
這一系列方法都是可以在觀察者回撥之前執行操作
public final Flowable<T> doOnDispose(Action onCancel)
public final Flowable<T> doOnComplete(Action onComplete)
public final Flowable<T> doOnEach(Consumer<? super Notification<T>> onNotification)
// 傳送任何事件都會觸發回撥(包括onError onComplete)
public final Flowable<T> doOnEach(org.reactivestreams.Subscriber<? super T> subscriber)
public final Flowable<T> doOnError(Consumer<? super java.lang.Throwable> onError)
public final Flowable<T> doOnLifecycle(Consumer<? super org.reactivestreams.Subscription> onSubscribe,
LongConsumer onRequest,
Action onCancel)
public final Flowable<T> doOnNext(Consumer<? super T> onNext)
public final Flowable<T> doOnRequest(LongConsumer onRequest)
// 該方法用於跟蹤背壓, 常常用於除錯, 故Observable沒有該方法
public final Flowable<T> doOnSubscribe(Consumer<? super org.reactivestreams.Subscription> onSubscribe)
// 在訂閱被觀察者前回撥
public final Flowable<T> doOnTerminate(Action onTerminate)
// 該回撥會在onComplete和onError方法前回撥, 無論是異常還是完成
複製程式碼
Notification
因為doOnEach回撥會在所有事件都觸發, 所以Notification包含了所有事件的資訊
java.lang.Throwable getError()
// 如果觸發的事件是onError則會返回異常資訊, 否則null
T getValue()
// 如果觸發的事件是onNext則會返回該值, 否則返回null
boolean isOnComplete()
boolean isOnError()
boolean isOnNext()
// Notification提供靜態方法直接構成出三種事件的例項物件
static <T> Notification<T> createOnComplete()
static <T> Notification<T> createOnError(java.lang.Throwable error)
static <T> Notification<T> createOnNext(T value)
複製程式碼
建立操作符
建立操作符全部屬於靜態方法呼叫
建立被觀察者
Create
public static <T> Observable<T> create(ObservableOnSubscribe<T> source)
複製程式碼
ObservableOnSubscribe中只有一個方法
void subscribe(ObservableEmitter<T> e)
throws java.lang.Exception
複製程式碼
ObservableEmitter
譯為發射器. 可以通過三種方法傳送事件
void onComplete()
void onError(java.lang.Throwable error)
void onNext(T value)
複製程式碼
Tip:
onError()
和onComplete()
不能同時使用onError()
不能多次使用,onComplete()
可以
其他方法:
void setCancellable(Cancellable c)
// 設定一個取消事件監聽器
void setDisposable(Disposable d)
boolean isDisposed()
複製程式碼
Just
通過直接傳入N個引數來批量傳送事件(最多九個引數)
static <T> Observable<T> just(T item)
複製程式碼
全部事件傳送完畢後會回撥onComplete方法
FromArray
通過傳入陣列或者集合來傳送事件
static <T> Observable<T> fromArray(T... items)
複製程式碼
FromIterable
Iterable是可遍歷集合的根介面, 可以通過傳送集合;
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
Flowable.fromIterable(list).subscribe(
s -> Log.i("tag", s)
);
複製程式碼
更多的方法
- Javadoc: from(array)
- Javadoc: from(Iterable)
- Javadoc: from(Future)
- Javadoc: from(Future,Scheduler)
- Javadoc: from(Future,timeout, timeUnit)
defer
只能夠在回撥函式中建立被觀察者
public static <T> Observable<T> defer(java.util.concurrent.Callable<? extends ObservableSource<? extends T>> supplier)
複製程式碼
追加事件
StartWith
在已經建立的事件前面再新增事件
public final Observable<T> startWith(T item)
public final Observable<T> startWithArray(T... items)
複製程式碼
直接結束事件
Empty
不傳送任何事件給觀察者, 立即回撥onComplete()
Flowable.empty().subscribe(
obj -> Log.i("tag", "next" + obj.toString()),
e -> Log.i("tag", "error"),
() -> Log.i("tag", "complete"));
複製程式碼
Never
不傳送任何事件給觀察者, 並且不執行任何方法(例如OnComplete)
Error
不傳送任何事件, 但是會直接執行onError()
輪循器
Interval
定時控制間隔傳送事件. 預設在計算執行緒(ComputationScheduler), 可以指定執行緒.
只能控制間隔時間
public static Observable<java.lang.Long> interval(long period,
java.util.concurrent.TimeUnit unit)
public static Observable<java.lang.Long> interval(long initialDelay, // 第一次的延遲時間
long period, // 間隔時間
java.util.concurrent.TimeUnit unit) // 時間單位
複製程式碼
IntervalRange
更加精確的範圍內傳送計時器事件, 預設在計算執行緒(ComputationScheduler), 可以指定執行緒.
可以控制傳送次數
public static Observable<java.lang.Long> intervalRange(long start, // 開始數字
long count, // 總共次數
long initialDelay, // 初始間隔時間
long period, // 後面每次間隔時間
java.util.concurrent.TimeUnit unit) // 時間單位
複製程式碼
Range
可以設定傳送次數的定時器, 沒有預設在特定的執行緒執行; 不會根據時間傳送, 直接一次性按照按照順序傳送完畢.
// 傳送int事件型別
public static Observable<java.lang.Integer> range(int start, // 開始
int count) // 結束
// 傳送long的事件型別
public static Observable<java.lang.Long> rangeLong(long start,
long count)
複製程式碼
Timer
定時器操作符. Timer預設在computationScheduler(計算執行緒)上執行, 可以指定執行緒.
public static Observable<java.lang.Long> timer(long delay, // 間隔時間
java.util.concurrent.TimeUnit unit) // 時間單位
複製程式碼
TimerInterval
記錄輪循器的資訊
- 時間間隔
- 時間單位
- 值
public final Observable<Timed<T>> timeInterval()
// 時間間隔設定固定單位
public final Observable<Timed<T>> timeInterval(java.util.concurrent.TimeUnit unit)
複製程式碼
輸出示例:
// 無參預設單位為毫秒
Timed[time=1003, unit=MILLISECONDS, value=12]
// 設定單位為秒
Timed[time=1, unit=SECONDS, value=40]
複製程式碼
Repeat
重複傳送事件
- 無限迴圈
- 指定時間內迴圈
- 停止
public final Observable<T> repeat()
// 無限迴圈
public final Observable<T> repeat(long times)
// 設定迴圈次數
public final Observable<T> repeatUntil(BooleanSupplier stop)
// 設定迴圈結束條件
// 新增一個被觀察者作為重新傳送事件的條件
public final Observable<T> repeatWhen(Function<? super Observable<java.lang.Object>,? extends ObservableSource<?>> handler)
複製程式碼
示例
io.reactivex.Observable.just(1)
.repeatUntil(
new BooleanSupplier() {
/**
* @return 返回true表示結束迴圈
* @throws Exception
*/
@Override
public boolean getAsBoolean() throws Exception {
return true;
}
})
.subscribe(System.out::println);
複製程式碼
RepeatWhen
如果回撥函式中的被觀察者傳送onComplete和onError事件不會進入重複事件
但是如果傳送onNext事件就會導致重複傳送
Observable.intervalRange(0, 5, 1, 1, TimeUnit.SECONDS, TrampolineScheduler.instance())
.repeatWhen(
new Function<Observable<Object>, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Observable<Object> objectObservable)
throws Exception {
// 源被觀察者結束後(onComplete)等待五秒再次重新傳送
return Observable.interval(5, TimeUnit.SECONDS);
}
})
.subscribe(
new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
// do something
}
});
複製程式碼
多觀察者建立
Concat
將多個被觀察者連線起來按照順序傳送
ConcatArray
和Concat
操作符其實都一樣, 只不過可以接受陣列而已
Merge
將多個被觀察者合併, 遵守時間順序(不遵守引數新增順序)
public static <T> Observable<T> mergeArray(int maxConcurrency,
int bufferSize,
ObservableSource<? extends T>... sources)
複製程式碼
Zip
可以將多個發射器傳送的事件對應傳送順序組合成一個然後統一一次接收事件, 遵守兩兩合併的原則.
如果存在非同步情況, 將會等待需要合併的兩個事件同時執行完畢後再傳送給觀察者;
- 遵守訂閱順序
public static <T,R> Observable<R> zip(ObservableSource<? extends ObservableSource<? extends T>> sources,
Function<? super java.lang.Object[],? extends R> zipper)
複製程式碼
示例:
Observable.zip(getStringObservable(), getIntegerObservable(),
new BiFunction<String, Integer, String>() {
@Override public String apply(@NonNull String s, @NonNull Integer integer)
throws Exception {
// 在這裡將兩個發射器的事件合併然後統一傳送
return s + integer;
}
}).subscribe(new Consumer<String>() {
@Override public void accept(@NonNull String s) throws Exception {
// 這裡只會接受到apply的返回值
}
});
複製程式碼
ZipWith
將傳入的被觀察者和源被觀察者對應組合(Zip)該方法屬於非靜態方法
Observable.just(1).zipWith(Observable.just(2), new BiFunction<Integer, Integer, String>() {
@Override
public String apply(Integer integer, Integer integer2) throws Exception {
System.out.println("integer = [" + integer + "], integer2 = [" + integer2 + "]");
return integer + "" + integer2;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
// 結果: s = [12]
System.out.println("s = [" + s + "]");
}
});
複製程式碼
CombineLast
最後一個被觀察者的所有事件依次和前面的被觀察者的最後一個事件合併.
- 遵守訂閱觀察者順序
public static <T1,T2,T3,R> Observable<R> combineLatest(ObservableSource<? extends T1> source1,
ObservableSource<? extends T2> source2,
Function3<? super T1,? super T2,? super T3,? extends R> combiner)
複製程式碼
示例結果:
最後一個被觀察者和之前的所有的被觀察者的最後一個事件同時被接收到
s = [輪循器一10輪循器二10輪循器三1]
s = [輪循器一10輪循器二10輪循器三2]
s = [輪循器一10輪循器二10輪循器三3]
s = [輪循器一10輪循器二10輪循器三4]
s = [輪循器一10輪循器二10輪循器三5]
s = [輪循器一10輪循器二10輪循器三6]
s = [輪循器一10輪循器二10輪循器三7]
s = [輪循器一10輪循器二10輪循器三8]
s = [輪循器一10輪循器二10輪循器三9]
s = [輪循器一10輪循器二10輪循器三10]
複製程式碼
變化操作符
轉換Observable
FlatMap
將事件攔截然後轉成被觀察者再次傳送
交錯順序, 即發射器傳送事件的時候可能是非同步或者延遲的.
public final <R> Observable<R> flatMap(Function<? super T,? extends ObservableSource<? extends R>> mapper)
// onNext/onError/onComplete 分別回撥
public final <R> Observable<R> flatMap(Function<? super T,? extends ObservableSource<? extends R>> onNextMapper,
Function<? super java.lang.Throwable,? extends ObservableSource<? extends R>> onErrorMapper,
java.util.concurrent.Callable<? extends ObservableSource<? extends R>> onCompleteSupplier)
public final <U,R> Observable<R> flatMap(Function<? super T,? extends ObservableSource<? extends U>> mapper,
BiFunction<? super T,? super U,? extends R> resultSelector)
複製程式碼
FlatMapIterable
public final <U> Observable<U> flatMapIterable(Function<? super T,? extends java.lang.Iterable<? extends U>> mapper)
// 就是轉成集合型別被觀察者接收到
複製程式碼
過載方法將可迭代物件最終又轉換成單個物件
public final <U,V> Observable<V> flatMapIterable(
Function<? super T,? extends java.lang.Iterable<? extends U>> mapper,
BiFunction<? super T,? super U,? extends V> resultSelector)
複製程式碼
示例
Observable.just(1, 2, 3, 4, 5).flatMapIterable(new Function<Integer, Iterable<String>>() {
@Override public Iterable<String> apply(Integer integer) throws Exception {
Log.d("日誌",
"(MainActivity.java:32) ___ " + "apply() called with: integer = [" + integer + "]");
// iterable屬於所有集合的根介面
ArrayList<String> strings = new ArrayList<>();
strings.add(integer.toString() + "集合中");
return strings;
}
}, new BiFunction<Integer, Object, String>() {
/**
* 得到一個最終被觀察者接受的事件
* @param t1 發射器的事件
* @param t2 被新增到集合中物件
* @return 最終被觀察者接受的事件
* @throws Exception 如果返回null將丟擲異常
*/
@Override public String apply(Integer integer, Object o) throws Exception {
Log.d("日誌", "(MainActivity.java:39) ___ "
+ "apply() called with: integer = ["
+ integer
+ "], o = ["
+ o
+ "]");
// 如果返回null則會丟擲異常進入onError
return "吳彥祖";
}
}).subscribe(new Observer<String>() {
@Override public void onSubscribe(Disposable d) {
Log.i("日誌", "(MainActivity.java:49) ___ onSubscribe");
}
@Override public void onNext(String s) {
Log.d("日誌", "(MainActivity.java:53) ___ " + "onNext() called with: s = [" + s + "]");
}
@Override public void onError(Throwable e) {
Log.i("日誌", "(MainActivity.java:57) ___ onError");
}
@Override public void onComplete() {
Log.i("日誌", "(MainActivity.java:61) ___ onComplete");
}
});
複製程式碼
FatMapCompletable
只能接受到onComplete回撥
public final Completable flatMapCompletable(Function<? super T,? extends CompletableSource> mapper)
public final Completable flatMapCompletable(Function<? super T,? extends CompletableSource> mapper,
boolean delayErrors)
複製程式碼
FlatMapMaybe
public final <R> Observable<R> flatMapMaybe(Function<? super T,? extends MaybeSource<? extends R>> mapper);
public final <R> Observable<R> flatMapMaybe(Function<? super T,? extends MaybeSource<? extends R>> mapper,
boolean delayErrors)
複製程式碼
FlatMapSingle
單一接受者
public final <R> Observable<R> flatMapSingle(Function<? super T,? extends SingleSource<? extends R>> mapper)
public final <R> Observable<R> flatMapSingle(Function<? super T,? extends SingleSource<? extends R>> mapper,
boolean delayErrors)
複製程式碼
ConcatMap
和FlatMap的區別是保證順序發射(不存在交錯順序), 內部使用Concat實現;
例如: 兩個非同步的被觀察者無論如何都會按照你引數新增的順序傳送事件
public final <R> Flowable<R> concatMap(Function<? super T,? extends org.reactivestreams.Publisher<? extends R>> mapper)
public final <R> Flowable<R> concatMap(Function<? super T,? extends org.reactivestreams.Publisher<? extends R>> mapper,
int prefetch)
複製程式碼
ConcatMapDelayError
延遲異常丟擲到所有事件傳送完畢後
public final <R> Flowable<R> concatMapDelayError(Function<? super T,? extends org.reactivestreams.Publisher<? extends R>> mapper)
public final <R> Flowable<R> concatMapDelayError(Function<? super T,? extends org.reactivestreams.Publisher<? extends R>> mapper,
int prefetch,
boolean tillTheEnd)
複製程式碼
ConcatMapEager
將所有被觀察者的事件全部新增到一個被觀察者上, 然後一次性傳送;
public final <R> Observable<R> concatMapEager(Function<? super T,? extends ObservableSource<? extends R>> mapper)
複製程式碼
事件變化
Map
將型別轉換
public final <R> Flowable<R> map(Function<? super T,? extends R> mapper)
複製程式碼
SwitchMap
每次源被觀察者傳送資料的時候都會向觀察者傳送一個新的被觀察者, 但是如果有延遲操作就只會傳送最後一個源被觀察者建立的新被觀察者;
在RxJava2之前SwitchMap叫做FlatMapLatest, 這樣是否更加容易理解
public final <R> Observable<R> switchMap(Function<? super T,? extends ObservableSource<? extends R>> mapper)
複製程式碼
示例
Observable.just(1, 2, 3)
.switchMap(new Function<Integer, ObservableSource<?>>() {
@Override
public ObservableSource<Long> apply(Integer integer) throws Exception {
return interval1;
}
})
.subscribe(ele -> Log.d("日誌", "(MainActivity.java:39) ___ Result = " + ele));
複製程式碼
包裝事件成容器
Buffer
建立一個List集合儲存事件傳送給觀察者
- 數量
- 跨度
- 時間
public final Observable<java.util.List<T>> buffer(int count) // 向List中新增事件數量
public final Observable<java.util.List<T>> buffer(int count,
int skip) // 分段事件跨度
複製程式碼
例如: {1.2.3.4.5} count = 3, skip = 2.
接收到的事件就為 {1,2,3} {3,4,5} {5}
public final <B> Observable<java.util.List<T>> buffer(java.util.concurrent.Callable<? extends ObservableSource<B>> boundarySupplier)
// 在回撥介面中boundarySupplier封裝成集合Collection
// 快取一定時間內的事件新增到集合中
public final Observable<java.util.List<T>> buffer(long timespan,
long timeskip,
java.util.concurrent.TimeUnit unit)
複製程式碼
Window
建立一個被觀察者儲存事件傳送給觀察者
類似Buffer但是分組的結果是被觀察者, 類似GroupBy但是不是依靠於Key來分組;
分時間
public final Observable<Observable<T>> window(long timespan,
java.util.concurrent.TimeUnit unit)
// 按照時間跨度分組
public final Observable<Observable<T>> window(long timespan,
java.util.concurrent.TimeUnit unit,
long count)
// 按照時間跨度內的數量分組 (規定事件內只能新增規定數量的事件到被觀察者內)
public final Observable<Observable<T>> window(long timespan,
long timeskip,
java.util.concurrent.TimeUnit unit)
// 按照時間跨度分組
public final Observable<Observable<T>> window(long timespan,
java.util.concurrent.TimeUnit unit,
long count,
boolean restart)
複製程式碼
分觀察者傳送
類似Buffer, 不同的是Buffer是將事件封裝成一個List集合, 而Window是將一定事件數量封裝成一個新的被觀察者.
public final Observable<Observable<T>> window(long count)
// 按照數量分組
public final Observable<Observable<T>> window(long count,
long skip)
// 按照跨度分組
複製程式碼
示例
Observable.just(1, 2, 3, 4).window(3).subscribe(new Consumer<Observable<Integer>>() {
@Override public void accept(Observable<Integer> integerObservable) throws Exception {
Log.i("日誌", "(MainActivity.java:19) ___ 觀察者");
integerObservable.subscribe(new Consumer<Integer>() {
@Override public void accept(Integer integer) throws Exception {
Log.i("日誌", "(MainActivity.java:23) ___ 接受到事件");
}
});
}
});
複製程式碼
public final <B> Observable<Observable<T>> window(java.util.concurrent.Callable<? extends ObservableSource<B>> boundary)
public final <U,V> Observable<Observable<T>> window(ObservableSource<U> openingIndicator,
Function<? super U,? extends ObservableSource<V>> closingIndicator)
public final <U,V> Observable<Observable<T>> window(ObservableSource<U> openingIndicator,
Function<? super U,? extends ObservableSource<V>> closingIndicator,
int bufferSize)
複製程式碼
GroupBy
根據key將Observable被觀察者的事件分組變更為GroupedObservable
, 該類繼承自Observable, 但是新增一個方法
getKey()
可以獲取回撥中返回物件key;
// 在回撥中通過key來分組
public final <K> Observable<GroupedObservable<K,T>> groupBy(Function<? super T,? extends K> keySelector)
// 分組然後再次傳送事件
public final <K,V> Observable<GroupedObservable<K,V>> groupBy(Function<? super T,? extends K> keySelector,
Function<? super T,? extends V> valueSelector)
複製程式碼
Scan
public final Flowable<T> scan(BiFunction<T,T,T> accumulator)
public final <R> Flowable<R> scan(R initialValue,
BiFunction<R,? super T,R> accumulator)
複製程式碼
回撥返回值將作為下次回撥方法的第一個引數
Observable.just(1, 2, 3, 4, 5).scan(110, new BiFunction<Integer, Integer, Integer>() {
/**
* 第一次發射器發射的值會由觀察者接收到, 如果設定了initialValue則第一次接收到該初始值. 然後後面都會該方法的返回值
* @return 返回的值最終被觀察者接受到
* @throws Exception on error
*/
@Override
public Integer apply(Integer integer, Integer integer2) throws Exception {
return integer2 + 1;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("日誌",
"(MainActivity.java:37) ___ " + "accept() called with: integer = [" + integer + "]");
}
});
複製程式碼
ScanWith
第一個回撥函式中返回值是第二個回撥函式中的第一個引數(即初始值)
public final <R> Flowable<R> scanWith(java.util.concurrent.Callable<R> seedSupplier,
BiFunction<R,? super T,R> accumulator)
複製程式碼
ToList
將事件轉成集合一次接受; 但是主要要求被觀察者的事件型別統一;
public final Single<java.util.List<T>> toList()
public final Single<java.util.List<T>> toList(int capacityHint)
// 集合初始化空間
public final <U extends java.util.Collection<? super T>> Single<U> toList(java.util.concurrent.Callable<U> collectionSupplier)
複製程式碼
過濾操作符
延遲
Delay
delay
操作符會延遲每個事件傳送的時間(包括onComplete但包括onError)
public final Observable<T> delay(long delay,
java.util.concurrent.TimeUnit unit)
// 延遲時間單位
public final <U> Observable<T> delay(Function<? super T,? extends ObservableSource<U>> itemDelay)
// 在回撥中通過觀察者演出
複製程式碼
Observable.just(1, 2, 3)
.delay(
new Function<Integer, ObservableSource<Integer>>() {
/**
* 每次源被觀察者傳送事件都會執行該方法, 但是事件不會被觀察者接收到(處於延遲中).
*
* @param integer 事件
* @return 返回的被觀察者, 當這個觀察者傳送事件的時候將終止延遲
* @throws Exception
*/
@Override
public ObservableSource<Integer> apply(Integer integer) throws Exception {
System.out.println("integer = [" + integer + "]");
return Observable.just(1)
.delay(3, TimeUnit.SECONDS, TrampolineScheduler.instance());
}
})
.subscribe(
new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("result = [" + integer + "]");
}
});
複製程式碼
去除重複事件
Distinct
相同事件去重
public final Flowable<T> distinct()
// 去除所有重複的事件
public final <K> Observable<T> distinct(Function<? super T,K> keySelector)
// 在回撥內返回一個泛型值, 然後比較該泛型值來判斷是否屬於重複
public final <K> Observable<T> distinct(Function<? super T,K> keySelector,
java.util.concurrent.Callable<? extends java.util.Collection<? super K>> collectionSupplier)
複製程式碼
示例:
/*演示只取兩個偶數*/
Observable.just(1, 2, 3, 4, 5, 6).distinct(new Function<Integer, String>() {
/**
* 該方法每次傳送事件都會回撥
* @throws Exception
*/
@Override public String apply(Integer integer) throws Exception {
return integer % 2 == 0 ? "偶數" : "奇數";
}
}).subscribe(new Consumer<Integer>() {
@Override public void accept(Integer integer) throws Exception {
Log.d("日誌",
"(MainActivity.java:34) ___ " + "accept() called with: integer = [" + integer + "]");
}
});
複製程式碼
distinctUntilChanged
去除臨近的重複事件
public final Flowable<T> distinctUntilChanged()
// 只會去除鄰近的重複事件
public final Observable<T> distinctUntilChanged(BiPredicate<? super T,? super T> comparer)
// 該回撥會每次返回鄰近的兩個事件, 然後你自己在回撥內比較兩個值是否算重複, 返回布林型別
public final <K> Observable<T> distinctUntilChanged(Function<? super T,K> keySelector)
// 在回撥內返回一個泛型值, 然後比較該泛型值來判斷是否屬於重複
複製程式碼
示例:
Observable.just(1, 2, 2, 4, 5, 6).distinctUntilChanged(new BiPredicate<Integer, Integer>() {
@Override public boolean test(Integer integer, Integer integer2) throws Exception {
return integer.equals(integer2);
}
}).subscribe(new Consumer<Integer>() {
@Override public void accept(Integer integer) throws Exception {
Log.d("日誌",
"(MainActivity.java:34) ___ " + "accept() called with: integer = [" + integer + "]");
}
});
複製程式碼
只傳送指定資料
Element
只傳送指定位置(索引)的事件
public final Maybe<T> elementAt(long index) // 索引
public final Single<T> elementAt(long index,
T defaultItem) // 索引越界後傳送事件
public final Maybe<T> firstElement()
// 只傳送第一個
public final Maybe<T> lastElement()
public final Completable ignoreElements()
// 忽略全部事件
public final Single<T> elementAtOrError(long index)
// 如果事件為空, 則會丟擲異常
複製程式碼
Debounce
傳送事件後的一定時間內再次傳送的事件都會被捨棄, 並且重新開始計時.
這個場景常用語搜尋輸入框的自動提示: 你連續輸入文字會不斷地傳送事件,即會導致時間不斷地被重置始終無法成功傳送事件. 只有你在停止輸入後才會成功傳送事件.
public final <U> Observable<T> debounce(Function<? super T,? extends ObservableSource<U>> debounceSelector)
public final Observable<T> debounce(long timeout,
java.util.concurrent.TimeUnit unit)
複製程式碼
同樣還有一種實現方式
public final Observable<T> throttleWithTimeout(long timeout,
public final Observable<T> throttleWithTimeout(long timeout,
java.util.concurrent.TimeUnit unit,
Scheduler scheduler)
複製程式碼
Filter
篩選事件,例如字串為空則不傳送事件
Observable.just(1, 20, 65, -5, 7, 19)
.filter(new Predicate<Integer>() {
@Override
public boolean test(@NonNull Integer integer) throws Exception {
// 根據返回結果布林型別確定是否攔截事件
return integer >= 10;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer) throws Exception {
}
});
複製程式碼
All
判斷所有事件是否符合條件, 回撥函式會執行多次但是觀察者只能收到一個布林型別值;
public final Single<java.lang.Boolean> all(Predicate<? super T> predicate)
複製程式碼
Flowable.just(1, 2, 3, 4).all(new Predicate<Integer>() {
@Override public boolean test(Integer integer) throws Exception {
return integer < 4;
}
}).subscribe(new Consumer<Boolean>() {
@Override public void accept(Boolean aBoolean) throws Exception {
}
});
複製程式碼
First
只發射第一個事件, 否則就發射預設的事件
public final Single<T> first(T defaultItem)
public final Single<T> firstOrError()
// 如果為空則丟擲異常進入OnError()
複製程式碼
Last
只發射最後一個事件, 否則就發射預設的事件
public final Single<T> last(T defaultItem)
複製程式碼
Amb
僅僅處理第一個發射事件的被觀察者, 其他的觀察者都會被拋棄.
要求新增的所有被觀察者的事件型別需要統一;
public static <T> Observable<T> amb(java.lang.Iterable<? extends ObservableSource<? extends T>> sources)
// 集合型別
複製程式碼
ambArray
public static <T> Observable<T> ambArray(ObservableSource<? extends T>... sources)
// 可變引數型別
複製程式碼
ambWith
非靜態函式, 結束對源被觀察者的訂閱, 然後對當前指定引數的被觀察者訂閱;
public final Observable<T> ambWith(ObservableSource<? extends T> other)
複製程式碼
Blocking
該操作符會打斷RxJava的鏈式呼叫;
只傳送第一個或者最後一個事件
public final T blockingFirst()
public final T blockingFirst(T defaultItem)
public final T blockingLast()
public final T blockingLast(T defaultItem)
public final T blockingSingle()
複製程式碼
- 如果沒有設定預設值的話, 被觀察者事件為空將丟擲異常
- 使用single, 但是如果observable的事件不止一個, 將丟擲異常
示例:
Long aLong = Observable.intervalRange(0, 5, 1, 1, TimeUnit.SECONDS)
.blockingFirst();
複製程式碼
迴圈
public final void blockingForEach(Consumer<? super T> onNext)
public final java.lang.Iterable<T> blockingIterable()
public final java.lang.Iterable<T> blockingIterable(int bufferSize)
public final java.lang.Iterable<T> blockingMostRecent(T initialValue)
public final void blockingSubscribe()
複製程式碼
限制接受事件
- 指定時間內 第一個
- 指定時間內 最後一個
throttleFirst
只傳送一定時間內的第一個事件, 預設在ComputationScheduler上執行, 但是可以指定Scheduler
public final Observable<T> throttleFirst(long windowDuration,
java.util.concurrent.TimeUnit unit)
public final Observable<T> throttleFirst(long skipDuration,
java.util.concurrent.TimeUnit unit,
Scheduler scheduler)
複製程式碼
throttleLast
只傳送一定時間內的最後一個事件
public final Observable<T> throttleLast(long intervalDuration,
java.util.concurrent.TimeUnit unit)
public final Observable<T> throttleLast(long intervalDuration,
java.util.concurrent.TimeUnit unit,
Scheduler scheduler)
複製程式碼
throttleWithTimeout
傳送事件A後將觸發計時, 如果規定時間內有新的事件B傳送, 將丟棄事件A; 功能和debounce
相同, 但是debounce
可以新增一個Observable作為計時;
public final Observable<T> throttleWithTimeout(long timeout,
java.util.concurrent.TimeUnit unit)
public final Observable<T> throttleWithTimeout(long timeout,
java.util.concurrent.TimeUnit unit,
Scheduler scheduler)
複製程式碼
Sample
控制間隔, 在一定時間內只取最後發射的事件, 可以指定執行緒. 等同於throttleLast
public final Observable<T> sample(long period,
java.util.concurrent.TimeUnit unit)
public final Observable<T> sample(long period,
java.util.concurrent.TimeUnit unit,
boolean emitLast)
複製程式碼
public final <U> Observable<T> sample(ObservableSource<U> sampler)
public final <U> Observable<T> sample(ObservableSource<U> sampler,
boolean emitLast)
複製程式碼
TimeOut
public final Observable<T> timeout(long timeout,
java.util.concurrent.TimeUnit timeUnit)
public final Observable<T> timeout(long timeout,
java.util.concurrent.TimeUnit timeUnit,
ObservableSource<? extends T> other)
複製程式碼
- 設定一個超時的時間間隔, 如果傳送事件的間隔超過這個事件就會發出一個異常事件TimeoutException(進入onError).
- 如果你不想發出的是異常而是傳送一個新的被觀察者事件, 就可以使用該方法
和上面的操作符不同的是, 這個操作符是通過回撥函式返回的Observable來控制超時時間; 如果返回的Observable傳送了事件但是源被觀察者還未傳送事件, 將判斷為超時; 進入onError丟擲TimeOutException
public final <V> Observable<T> timeout(Function<? super T,? extends ObservableSource<V>> itemTimeoutIndicator)
public final <V> Observable<T> timeout(Function<? super T,? extends ObservableSource<V>> itemTimeoutIndicator,
ObservableSource<? extends T> other)
複製程式碼
以下過載可以給第一項被觀察者傳送的事件單獨設定一個超時引數(Observable)
public final <U,V> Observable<T> timeout(ObservableSource<U> firstTimeoutIndicator,
Function<? super T,? extends ObservableSource<V>> itemTimeoutIndicator)
public final <U,V> Observable<T> timeout(ObservableSource<U> firstTimeoutIndicator,
Function<? super T,? extends ObservableSource<V>> itemTimeoutIndicator,
ObservableSource<? extends T> other)
複製程式碼
跳過事件
- 數量
- 指定時間
- 倒序跳過
- 指定被觀察者傳送完畢
- 回撥函式連續跳過
Skip
跳過事件
public final Observable<T> skip(long count)
// 跳過指定數量的事件
public final Observable<T> skip(long time,
java.util.concurrent.TimeUnit unit)
// 跳過指定時間內的事件
複製程式碼
SkipLast
從後開始跳過傳送事件;
public final Observable<T> skipLast(int count)
public final Observable<T> skipLast(long time,
java.util.concurrent.TimeUnit unit)
public final Flowable<T> skipLast(long time,
java.util.concurrent.TimeUnit unit,
boolean delayError)
複製程式碼
SkipUntil
在作為引數的被觀察者沒有傳送完事件之前的所有源被觀察者的事件都將被跳過;
public final <U> Observable<T> skipUntil(ObservableSource<U> other)
複製程式碼
示例程式碼:
Observable.intervalRange(0, 5, 1, 1, TimeUnit.SECONDS)
// 如果下面的被觀察者的事件沒有傳送完畢(不包括onComplete)源被觀察者的事件都將被跳過
.skipUntil(Observable.just(1)
.delay(2, TimeUnit.SECONDS))
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.d("日誌",
"(MainActivity.java:80) ___ " + "accept() called with: aLong = [" + aLong + "]");
}
});
複製程式碼
SkipWhile
在回撥中判斷是否拋棄事件;
和過濾操作符filter
不同的是skipWhile只能從開頭開始連續跳過事件, 即如果第一個事件你沒有跳過, 那麼該回撥函式就不會再次執行, 也就是你之後都無法跳過事件了;
public final Observable<T> skipWhile(Predicate<? super T> predicate)
複製程式碼
停止訂閱
- 可以接受的最多事件數量
- 可以接收到事件的時間
- 引數被觀察者傳送事件將停止源被觀察者的訂閱狀態
- 倒序
- 回撥函式判斷是否停止
Take
阻止發射器繼續發射事件, 結束以後會進入onComplete回撥
public final Observable<T> take(long count)
// 控制最多接受到的事件數量
public final Observable<T> take(long time,
java.util.concurrent.TimeUnit unit)
// 控制只有規定時間內才能接受到事件
複製程式碼
TakeUntil
public final <U> Observable<T> takeUntil(ObservableSource<U> other)
// 如果該引數指定的被觀察者傳送了事件就會結束之前的被觀察者的事件傳送
public final Observable<T> takeUntil(Predicate<? super T> stopPredicate)
// 通過回撥來判斷是否結束事件的傳送, 返回true結束髮射器發射事件
複製程式碼
TakeLast
public final Observable<T> takeLast(int count)
public final Observable<T> takeLast(long count,
long time,
java.util.concurrent.TimeUnit unit)
public final Observable<T> takeLast(long time,
java.util.concurrent.TimeUnit unit)
public final Observable<T> takeLast(long time,
java.util.concurrent.TimeUnit unit,
boolean delayError)
複製程式碼
TakeWhile
再回撥中判斷是否結束髮射器(同樣進入onComplete), 但是和TakeUntil不同的是返回false為結束.
public final Observable<T> takeWhile(Predicate<? super T> predicate)
複製程式碼
Join
新增一個被觀察者(稱為目標被觀察者), 該被觀察者傳送的每個事件都將依次和源被觀察者的所有事件結合(在同一個回撥函式中傳入)
public final <TRight,TLeftEnd,TRightEnd,R> Observable<R> join(ObservableSource<? extends TRight> other,
Function<? super T,? extends ObservableSource<TLeftEnd>> leftEnd,
Function<? super TRight,? extends ObservableSource<TRightEnd>> rightEnd,
BiFunction<? super T,? super TRight,? extends R> resultSelector)
複製程式碼
示例程式碼:
Observable.just(1L, 2L, 3L, 4L)
.join(Observable.just(5L, 6L, 7L, 8L), new Function<Long, ObservableSource<Long>>() {
/**
* 接受源被觀察者事件
* @param aLong
* @return 返回的被觀察者傳送事件後將終止源被觀察者的事件傳送
* @throws Exception
*/
@Override
public ObservableSource<Long> apply(Long aLong) throws Exception {
Log.d("日誌",
"(MainActivity.java:65) ___ " + "源被觀察者 aLong = [" + aLong + "]");
return Observable.interval(3, TimeUnit.SECONDS);
}
}, new Function<Long, ObservableSource<Long>>() {
/**
* 接受新增的被觀察者事件(join Observable)
* @param aLong
* @return 返回的被觀察者傳送事件後就將終止新增的被觀察者的
* @throws Exception
*/
@Override
public ObservableSource<Long> apply(Long aLong) throws Exception {
Log.d("日誌",
"(MainActivity.java:75) ___ " + "被新增的被觀察者 aLong = [" + aLong + "]");
return Observable.interval(3, TimeUnit.SECONDS);
}
}, new BiFunction<Long, Long, String>() {
/**
* 同時接受被新增的被觀察者和源被觀察者的事件
* @param aLong 源被觀察者傳送的事件
* @param aLong2 被新增的被觀察者傳送的事件
* @return 該返回值最終被觀察者接收到
* @throws Exception
*/
@Override
public String apply(Long aLong, Long aLong2) throws Exception {
Log.d("日誌", "(MainActivity.java:89) ___ " + "apply() called with: aLong = [" + aLong
+ "], aLong2 = [" + aLong2 + "]");
return aLong + "" + aLong2;
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("日誌", "(MainActivity.java:83) ___ " + "accept() called with: s = [" + s + "]");
}
});
複製程式碼
GroupJoin
和Join類似
public final <TRight,TLeftEnd,TRightEnd,R> Observable<R> groupJoin(ObservableSource<? extends TRight> other,
Function<? super T,? extends ObservableSource<TLeftEnd>> leftEnd,
Function<? super TRight,? extends ObservableSource<TRightEnd>> rightEnd,
BiFunction<? super T,? super Observable<TRight>,? extends R> resultSelector)
複製程式碼
示例:
Observable.just(1L, 2L, 3L, 4L)
.groupJoin(Observable.just(5L, 6L, 7L, 8L),
new Function<Long, ObservableSource<Long>>() {
@Override
public ObservableSource<Long> apply(Long aLong) throws Exception {
return null;
}
}, new Function<Long, ObservableSource<Long>>() {
@Override
public ObservableSource<Long> apply(Long aLong) throws Exception {
return null;
}
}, new BiFunction<Long, Observable<Long>, String>() {
@Override
public String apply(Long aLong, Observable<Long> longObservable) throws Exception {
return null;
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("日誌", "(MainActivity.java:78) ___ " + "accept() called with: s = [" + s + "]");
}
});
複製程式碼
ToMap
public final <K> Single<java.util.Map<K,T>> toMap(Function<? super T,? extends K> keySelector)
public final <K,V> Single<java.util.Map<K,V>> toMap(Function<? super T,? extends K> keySelector,
Function<? super T,? extends V> valueSelector)
public final <K,V> Single<java.util.Map<K,V>> toMap(Function<? super T,? extends K> keySelector,
Function<? super T,? extends V> valueSelector,
java.util.concurrent.Callable<? extends java.util.Map<K,V>> mapSupplier)
複製程式碼
錯誤處理
onErrorResumeNext
如果發生異常將接收到一個回撥返回另一個被觀察者(執行OnNext不執行onError)
// 訂閱另一個被觀察者
public final Observable<T> onErrorResumeNext(ObservableSource<? extends T> next)
複製程式碼
onErrorReturn
如果發生異常將接收到一個回撥返回事件(執行OnNext不執行onError)
public final Observable<T> onErrorReturn(Function<? super java.lang.Throwable,? extends T> valueSupplier)
複製程式碼
兩個操作符最後都會執行onComplete
Retry
當被觀察者的發射器發出異常事件(onError)以後會執行重試操作
public final Observable<T> retry()
// 當發生錯誤將重新傳送事件(被觀察者的所有事件全部重新傳送)
public final Observable<T> retry(long times)
// 重新傳送的次數
public final Observable<T> retry(Predicate<? super java.lang.Throwable> predicate)
public final Observable<T> retry(BiPredicate<? super java.lang.Integer,? super java.lang.Throwable> predicate)
// 在回撥函式中判斷是否重試(和上面的操作符不同的是該回撥函式裡面會有一個重試次數的引數)
public final Observable<T> retry(long times,
Predicate<? super java.lang.Throwable> predicate)
// 判斷函式 + 重試次數
複製程式碼
RetryUntil
該操作符其實Retry已經有相同實現retry(predicate)
不同的是返回true表示停止重試
public final Observable<T> retryUntil(BooleanSupplier stop)
複製程式碼
RetryWhen
在回撥函式中返回一個被觀察者, 該被觀察者如果發出錯誤事件就會導致源被觀察者重試. 如果沒有發出錯誤事件就不會觸發重試;
public final Observable<T> retryWhen(Function<? super Observable<java.lang.Throwable>,? extends ObservableSource<?>> handler)
複製程式碼
示例:
該示例不會觸發重試;
Observable.create(
new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onError(null);
emitter.onNext(3);
}
})
.retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
return Observable.just(23);
}
})
.subscribe(
new DefaultObserver<Integer>() {
@Override
public void onNext(Integer integer) {
System.out.println("integer = [" + integer + "]");
}
@Override
public void onError(Throwable e) {
System.out.println("Main.onError");
}
@Override
public void onComplete() {
System.out.println("Main.onComplete");
}
});
複製程式碼
判斷操作
Contains
判斷髮射的事件是否包含指定的事件, 觀察者得到一個布林型別的值
public final Single<java.lang.Boolean> contains(java.lang.Object element)
複製程式碼
Any
public final Single<java.lang.Boolean> any(Predicate<? super T> predicate)
複製程式碼
依次判斷每個事件, 如果返回true則馬上終止發射器
Observable.just(1, 2, 3, 4).any(new Predicate<Integer>() {
@Override public boolean test(Integer integer) throws Exception {
Log.d("日誌",
"(MainActivity.java:27) ___ " + "test() called with: integer = [" + integer + "]");
if (integer == 3) {
return true;
} else {
return false;
}
}
}).subscribe(new Consumer<Boolean>() {
@Override public void accept(Boolean aBoolean) throws Exception {
Log.d("日誌",
"(MainActivity.java:33) ___ " + "accept() called with: aBoolean = [" + aBoolean + "]");
}
});
複製程式碼
IsEmpty
public final Single<java.lang.Boolean> isEmpty()
複製程式碼
判斷是否有發射過事件, 觀察者得到個布林型別的值.
DefaultIfEmpty
public final Observable<T> defaultIfEmpty(T defaultItem)
複製程式碼
如果發射器沒有發射任何事件, 就會發射一個指定的預設事件, 例如發射器的事件被攔截
SwitchIfEmpty
public final Observable<T> switchIfEmpty(ObservableSource<? extends T> other)
複製程式碼
如果沒有發射事件就用另一個被觀察者替代
Flowable.empty()
.switchIfEmpty(Flowable.just(3, 4, 5))
.subscribe(ele -> Log.i("tag", String.valueOf(ele)));
複製程式碼
SequenceEqual
public static <T> Single<java.lang.Boolean> sequenceEqual(ObservableSource<? extends T> source1,
ObservableSource<? extends T> source2,
BiPredicate<? super T,? super T> isEqual)
// 最後的
public static <T> Single<java.lang.Boolean> sequenceEqual(ObservableSource<? extends T> source1,
ObservableSource<? extends T> source2)
複製程式碼
會比較兩個被觀察者是否相同, 然後觀察者接受一個布林型別的值, 發射的事件數量不相同, 型別不相同都會為false. 只要判斷到不相同馬上就會終止事件的傳送.
Observable.sequenceEqual(Observable.intervalRange(0, 3, 0, 1, TimeUnit.SECONDS),
Observable.just(0l, 1l, 2l), new BiPredicate<Long, Long>() {
@Override public boolean test(Long aLong, Long aLong2) throws Exception {
// 在這裡判斷是否相等
return false;
}
}).subscribe(new Consumer<Boolean>() {
@Override public void accept(Boolean aBoolean) throws Exception {
// 最終結果
}
});
複製程式碼
合併操作
Reduce
相加操作符, 每次都可以兩個事件一起處理, 然後所有事件都被處理後就會被觀察者接受到最終的事件
public final Maybe<T> reduce(BiFunction<T,T,T> reducer)
複製程式碼
第一次處理(apply)會接收到事件1和事件2, 然後第N次就是上次處理的結果(apply的返回值)和事件N
示例:
Observable.just(1, 2, 3, 4).reduce(new BiFunction<Integer, Integer, Integer>() {
/**
* 該方法會回撥多次直到所有事件都依次相加(或者說操作)以後才會被觀察者接收到最終的結果
* @throws Exception
*/
@Override public Integer apply(Integer integer, Integer integer2) throws Exception {
// 三個泛型分別對應 上次執行結果 當前事件 返回值
return integer + integer2;
}
}).subscribe(new Consumer<Integer>() {
@Override public void accept(Integer integer) throws Exception {
}
});
複製程式碼
待定操作符
public final <R> Single<R> reduce(R seed,
BiFunction<R,? super T,R> reducer)
public final <R> Single<R> reduceWith(java.util.concurrent.Callable<R> seedSupplier,
BiFunction<R,? super T,R> reducer)
複製程式碼
Scan
和Reduce類似, 但是每次觀察者都能收到經過操作的事件.
public final Observable<T> scan(BiFunction<T,T,T> accumulator)
複製程式碼
第一次觀察者就會接受到第一個事件, 後面才是被處理過後的事件.
後面介紹個過載方法, 可以單獨傳入一個初始化事件和待觀察事件組合.
public final <R> Observable<R> scan(R initialValue, // 加入一個初始化的值
BiFunction<R,? super T,R> accumulator)
複製程式碼
這裡我將initialValue
設定為"吳彥祖"
Observable.just(1, 2, 3, 4).scan("吳彥祖", new BiFunction<String, Integer, String>() {
@Override public String apply(String s, Integer integer) throws Exception {
Log.d("日誌", "(MainActivity.java:19) ___ "
+ "apply() called with: s = ["
+ s
+ "], integer = ["
+ integer
+ "]");
return s + integer;
}
}).subscribe(new Consumer<String>() {
@Override public void accept(String s) throws Exception {
}
});
複製程式碼
ScanWith
public final <R> Observable<R> scanWith(java.util.concurrent.Callable<R> seedSupplier,
BiFunction<R,? super T,R> accumulator)
複製程式碼
Collect
可以建立容器來依次運算元據(觀察者只會收到一次事件, 也就是容器)
Flowable.just(1, 2, 3)
.collect(
new Callable<ArrayList<Integer>>() {//建立收集容器
@Override
public ArrayList<Integer> call() throws Exception {
return new ArrayList<>();
}
}, new BiConsumer<ArrayList<Integer>, Integer>() {//建立收集
@Override
public void accept(ArrayList<Integer> list, Integer integer)
throws Exception {//前者容器,後者資料
list.add(integer);
}
})
.subscribe(ele -> Log.d("日誌", "(MainActivity.java:33) ___ Result = " + String.valueOf(ele)));
複製程式碼
Compose
public final <R> Observable<R> compose(ObservableTransformer<? super T,? extends R> composer)
複製程式碼
輔助操作符
時間統計
TimeStamp
該操作符將事件和傳送的時間都封裝到一個物件Timed
中
public final Observable<Timed<T>> timestamp()
public final Observable<Timed<T>> timestamp(Scheduler scheduler)
public final Observable<Timed<T>> timestamp(java.util.concurrent.TimeUnit unit)
public final Observable<Timed<T>> timestamp(java.util.concurrent.TimeUnit unit,
Scheduler scheduler)
複製程式碼
示例:
Observable.intervalRange(0, 5, 2, 2, TimeUnit.SECONDS)
.timestamp()
.subscribe(new Consumer<Timed<Long>>() {
@Override
public void accept(Timed<Long> longTimed) throws Exception {
Log.d("日誌",
"(MainActivity.java:62) ___ " + "accept() called with: longTimed = [" + longTimed
+ "]");
}
});
複製程式碼
結果
longTimed = [Timed[time=1525735346216, unit=MILLISECONDS, value=2]]
複製程式碼
計數器
Count
觀察者將接收到事件數量, 而無法收到事件本身.
Flowable.just(1,2,3,4,5).count().subscribe(new BiConsumer<Long, Throwable>() {
@Override public void accept(Long aLong, Throwable throwable) throws Exception {
Log.d("日誌", "(MainActivity.java:18) ___ Result = " + aLong);
}
});
複製程式碼
To
轉換操作符
public final <K,V> Single<java.util.Map<K,V>> toMap(Function<? super T,? extends K> keySelector,
Function<? super T,? extends V> valueSelector)
複製程式碼
BackPressure
意為"背壓"
瞭解了Observable和Flowable的區別,我們還不知什麼叫做背壓,下面我們來簡單瞭解下概念。所謂背壓就是生產者(被觀察者)的生產速度大於消費者(觀察者)消費速度從而導致的問題。
舉一個簡單點的例子,如果被觀察者快速傳送訊息,但是觀察者處理訊息的很緩慢,如果沒有特定的流(Flow)控制,就會導致大量訊息積壓佔用系統資源,最終導致十分緩慢。
同步執行緒是不可能產生這種問題, 觀察者沒有處理完事件就不可能再次傳送事件.
怎麼優化和減少這種情況後面再探討,不過可以注意到,Flowable建立的時候已經設定了BackpressureStrategy,而且Subscriber使用了request來控制最大的流量。
被觀察者
Observable
不支援背壓的被觀察者, 效能高;
Flowable
支援背壓的被觀察者, 效能比Observable低;
Publisher和ObservableSource
Publisher該類屬於Flowable的根介面, ObservableSource屬於Observable的根介面;
Single
該被觀察者只能發出一個事件, 重複傳送不會受到(因為只能傳送一條事件所以不存在背壓).
Single.create(new SingleOnSubscribe<Integer>() {
@Override public void subscribe(SingleEmitter<Integer> emitter) throws Exception {
emitter.onSuccess(1);
emitter.onSuccess(2);
}
}).subscribe(new Consumer<Integer>() {
@Override public void accept(Integer integer) throws Exception {
// 只會觸發一次事件
Log.d("日誌",
"(MainActivity.java:34) ___ " + "accept() called with: integer = [" + integer + "]");
}
});
複製程式碼
DisposableSingleObserver
可以手動斷開觀察者
public final void dispose()
public final boolean isDisposed()
複製程式碼
ResourceSingleObserver
可以新增其他的Disposable, 然後一起取消觀察者
public final void add(Disposable resource)
複製程式碼
其他被觀察者基本都遵守這幾個規則有類似名稱的觀察者類
Completable
如果你的觀察者連onNext事件都不關心,你可以使用Completable,他只有onComplete和onError兩個事件:
Completable.create(new CompletableOnSubscribe() {//被觀察者
@Override
public void subscribe(CompletableEmitter e) throws Exception {
e.onComplete();//單一onComplete或者onError
}
}).subscribe(new CompletableObserver() {//觀察者
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
}
@Override
public void onError(Throwable e) {
}
});
複製程式碼
同樣也可以使用Actions來簡化Observer:
- completable.subscribe(onComplete)
- completable.subscribe(onComplete,onError)
要轉換成其他型別的被觀察者,也是可以使用toFlowable()
、toObservable()
等方法去轉換。
Maybe
如果你有一個需求是可能傳送一個資料或者不會傳送任何資料,這時候你就需要Maybe,它類似於Single和Completable的混合體。
Maybe可能會呼叫以下其中一種情況(也就是所謂的Maybe):
- onSuccess或者onError
- onComplete或者onError
可以看到onSuccess和onComplete是互斥的存在,例子程式碼如下:
//被觀察者
Maybe<String> maybe = Maybe.create(new MaybeOnSubscribe<String>() {
@Override
public void subscribe(MaybeEmitter<String> e) throws Exception {
e.onSuccess("test");//傳送一個資料的情況,或者onError,不需要再呼叫onComplete(呼叫了也不會觸發onComplete回撥方法)
//e.onComplete();//不需要傳送資料的情況,或者onError
}
});
//訂閱觀察者
maybe.subscribe(new MaybeObserver<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(String s) {
//傳送一個資料時,相當於onNext和onComplete,但不會觸發另一個方法onComplete
Log.i("tag", s);
}
@Override
public void onComplete() {
//無資料傳送時候的onComplete事件
Log.i("tag", "onComplete");
}
@Override
public void onError(Throwable e) {
}
});
複製程式碼
Subject
AsyncSubject
- 該被觀察者只會傳送最後一個事件(同時
onComplete
) - 如果出現異常終止任何事件;
- 要求必須手動執行
onComplete()
才會接收到最後一個事件和onComplete
BehaviorSubject
- 該主題只會觀察訂閱前的最後一個傳送事件
onNext()
以及訂閱之後傳送的所有事件;
PublishSubject
- 只觀察訂閱後傳送的事件;
ReplaySubject
- 該主題無論訂閱前還是訂閱後傳送的事件都將會被觀察者接收到;
觀察者
-
Action:無引數型別
-
Consumer:單一引數型別
-
BiConsumer<T1, T2>:雙引數型別
-
Consumer<Obejct[]>:多引數型別
Callable
測試
用於測試RxJava的事件類
TestObserver
TestScheduler
對於某些需要經過一定時間的輪循器等事件觀察者
// 時間快速經過多少
public void advanceTimeBy(long delayTime,
java.util.concurrent.TimeUnit unit)
// 時間直接到某個點
public void advanceTimeTo(long delayTime,
java.util.concurrent.TimeUnit unit)
複製程式碼
TestSubsriber
@Test public void addition_isCorrect() throws Exception {
TestSubscriber<String> testSubscriber = new TestSubscriber<>();
//依次發射A,B,C
Flowable.just("A", "B", "C").subscribe(testSubscriber);
//斷言值是否不存在
testSubscriber.assertNever("D");
//斷言值是否相等
testSubscriber.assertValues("A", "B", "C");
//斷言值的數量是否相等
testSubscriber.assertValueCount(3);
//斷言是否結束
testSubscriber.assertTerminated();
}
複製程式碼
RxBinding
依賴(根據需要來新增依賴即可)
compile 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
compile 'com.jakewharton.rxbinding2:rxbinding-support-v4:2.1.1'
compile 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.1.1'
compile 'com.jakewharton.rxbinding2:rxbinding-design:2.1.1'
compile 'com.jakewharton.rxbinding2:rxbinding-recyclerview-v7:2.1.1'
複製程式碼
使用方式
AutoDispose
會根據Activity的生命週期, 自動解除RxJava的觀察者訂閱. 由Uber開源. Rxlifecycler作者推薦使用.
依賴:
compile 'com.uber.autodispose:autodispose-android:x.y.z'
複製程式碼
使用:
在OnDestroy
方法以後解除訂閱
Observable.interval(1, TimeUnit.SECONDS)
.as(
AutoDispose.autoDisposable(
AndroidLifecycleScopeProvider.from(this)))
.subscribe(
new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.d("日誌", "(MainActivity.java:33) ___ Result = " + aLong);
}
});
複製程式碼
as方法只能在subscribe之前
自定義生命週期
Observable.interval(1, TimeUnit.SECONDS)
.as(
AutoDispose.autoDisposable(
AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_STOP)))
.subscribe(
new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.d("日誌", "(MainActivity.java:33) ___ Result = " + aLong);
}
});
複製程式碼
RxBus
RxBus是一種實現方式而非單指某庫. 本文介紹的RxBus是GitHub Star最高的第三方庫. 主要特點是支援標記(tag)功能. 不支援粘性事件(粘性事件的缺點也比較明顯不做介紹);
依賴
compile 'com.hwangjr.rxbus:rxbus:1.0.6'
複製程式碼
訂閱事件
@Subscribe(
thread = EventThread.IMMEDIATE,
tags = {@Tag}
)
public void heardFromMouseMam(String mouseWar) {
Timber.e("Just heard from mouse mam: " + mouseWar + " from " + Thread.currentThread());
}
複製程式碼
多個標籤接受事件
@Subscribe(
thread = EventThread.IMMEDIATE,
tags = {@Tag(Constants.EventType.TAG_STORY)}
)
public void heardFromMouse(String mouseWar) {
Timber.e("Just heard from mouse: " + mouseWar + " from " + Thread.currentThread());
}
複製程式碼
自動傳送事件
@Produce(
thread = EventThread.NEW_THREAD,
tags = {@Tag}
)
public String tell() {
return "執行Tell方法" + Thread.currentThread();
}
複製程式碼