一、RxJava操作符概述
RxJava中的操作符就是為了提供函數式的特性,函數式最大的好處就是使得數據處理簡潔易懂。
操作符實質上就是RxJava函數式編程模式的體現,在上篇文章中,我詳細闡述了RxJava中觀察者模式、Iterator模式、函數式編程模式概念的解讀,詳情請戳→文章傳送門。
Rxjava操作符的類型眾多,在本文中,我詳細解釋如圖1.1所示的9種操作符。
圖1.1 RxJava操作符的分類
本項目案例代碼已上傳Github,詳情戳→GitHub案例代碼。
圖1.2 RxJava操作符案例圖
二、RxJava操作符詳解
1、創建操作符
創建操作符的分類如下圖所示,關于create操作符的詳細操作可在我的上篇文章中查看,在本文中不加以贅述,文章鏈接戳→文章傳送門。在本文中從from操作符開始介紹。
圖2.1? 創建操作符的分類
注:在這里,我將請求的不完整回調在父類中進行了封裝,具體代碼可查看GitHub的代碼鏈接。
①from操作符
在這里以發送數組為例,from操作符的使用代碼如下所示:
//from操作符,創建以數組內容發送事件的ObservableString[] observableArr =newString[]{"Alex","Payne"};//onNextAction、onErrorAction提取到父類中,具體代碼可查看GitHub的代碼鏈接Observable.from(observableArr).subscribe(onNextAction, onErrorAction);
首先,我們查看如下所示from操作符的結構圖,可以看到它有多種實現方式,但是有一個共同點,都會返回一個Observable對象。
圖2.1.1 from操作符操作結構圖
實質上,Observable將數組中的元素逐個進行發送,在發送過程中轉換為Observable對象。
進一步查看源碼,可得知from操作符的作用:將一個Iterable、一個Future、 或者一個數組,內部通過代理的方式轉換成一個Observable。
Future轉換為OnSubscribe是通過OnSubscribeToObservableFuture進行的,Iterable轉換通過OnSubscribeFromIterable進行。數組通過OnSubscribeFromArray轉換。
②just操作符
使用代碼如下所示:
//just操作符,創建將逐個內容進行發送的Observable,其內部發送內容在內部以from的操作符的方式進行轉換Observable.just("Alex","Payne").subscribe(onNextAction);
圖2.1.2 just操作符結構圖
查看just操作符的結構圖,結合源碼得知,just操作符將單個參數發送的內容通過ScalarSynchronousObservable轉換為一個新的Observable對象,而將多個參數發送的內容轉換為一個數組,然后將數組通過from操作符進行發送。
③interval操作符
interval操作符使用代碼如下所示:
//interval操作符,創建以1秒為事件間隔發送整數序列的ObservableObservable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread()).subscribe(onNextAction);
圖2.1.3 interval操作符結構圖
查看interval的結構圖,其只能發送Long類型的數,實質上其作用為:創建一個按固定時間間隔發射整數序列的Observable,這個序列為一個無限遞增的整數序列。
需要注意的是:interval默認在computation調度器上執行。你也可以傳遞一個可選的Scheduler參數來指定調度器。
④range操作符
range操作符使用的代碼如下所示:
//range操作符,創建以發送范圍內的整數序列的ObservableObservable.range(0,3).subscribe(onNextAction);
range操作符發射一個范圍內的有序整數序列,并且我們可以指定范圍的起始和長度
圖2.1.4 range操作符參數釋義
⑤repeat操作符
repeat操作符使用的代碼如下所示:
//repeat操作符,創建一個以N次重復發送數據的ObservableObservable.range(0,3).repeat(2).subscribe(onNextAction);
在這里需要強調一下,它不是創建一個Observable,而是重復發射原始Observable的數據序列,這個序列或者是無限的,或者通過repeat(n)指定重復次數。
2、變換操作符
在這里我介紹如下圖所示7種變換操作符,變換操作符的作用是將源Observable發送的數據進行變換。
圖2.1 變換操作符的分類
①map操作符
map操作符使用的代碼如下所示:
//map操作符,通過指定一個Func,將Observable轉換為另一個Observable對象并發送Observable.just("Alex_Payne")? ? ? ? ? ? ? ? ? .map(newFunc1() {? ? ? ? ? ? ? ? ? ? ? @Override? ? ? ? ? ? ? ? ? ? ? publicStringcall(Strings) {return"My Name is"+ s;? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? }).subscribe(onNextAction);
map操作符將源Observable發送的數據轉換為一個新的Observable對象。
在這里,Func1和Action的區別在于,Func1包裝的是有返回值的方法。另外,和ActionX 一樣,FuncX 也有多個,用于不同參數個數的方法。
FuncX 和 ActionX 的區別在 FuncX 包裝的是有返回值的方法。
②flatMap操作符
flatMap操作符使用的代碼如下所示:
//flatMap操作符,將Observable發送的數據集合轉換為Observable集合//flatMap的合并運行允許交叉,允許交錯的發送事件String[] observableArr = {"Alex","Max","Bruce","Frank","Tom"};? ? ? ? Observable.from(observableArr).flatMap(newFunc1>() {? ? ? ? ? ? ? @Override? ? ? ? ? ? ? public Observable call(Strings) {returnObservable.just("My Name is:"+ s);? ? ? ? ? ? ? }? ? ? ? }).subscribe(onNextAction);
源Observable通過flatMap操作符轉換為包含源Observable發送的所有子條目的Observable集合,可見下圖的示意圖,然后從Observable集合中逐個取出轉化為單個Observable對象進行發送。不同于map操作符的一點就是一對多的轉化。
圖2.2.2 flatMap轉換示意圖
它的應用場景可以體現在源Observable發送的內容為一個復雜的數據集,例如一個Bean對象,而該外層Bean對象中一個成員變量為另一個內層Bean對象,我們想要拆解外層Bean對象獲取內層Bean對象,就可以用flatMap操作符。
注意:FlatMap對這些Observables發射的數據做的是合并(merge)操作,因此它們可能是交錯的。
③concatMap操作符
concatMap操作符使用的代碼如下所示:
//concatMap操作符,將Observable發送的數據集合轉換為Observable集合//解決了flatMap的交叉問題,將發送的數據連接發送String[] observableArr = {"Alex","Max","Bruce","Frank","Tom"};? ? ? ? Observable.from(observableArr).concatMap(newFunc1>() {? ? ? ? ? ? ? @Override? ? ? ? ? ? ? public Observable call(Strings) {returnObservable.just("My Name is:"+ s);? ? ? ? ? ? ? }? ? ? ? }).subscribe(onNextAction);
concatMap操作符類似于flatMap操作符,不同的一點是它按次序連接。
④cast操作符
cast操作符使用的代碼如下所示:
//cast操作符,將類對象進行轉換Object[] objectsArr = {"1","2","3"};? ? ? ? Observable.from(objectsArr).cast(String.class).subscribe(onNextAction);
cast操作符將源Observable發送的數據都強制轉換為一個指定的類型,然后再發射數據。
需強調的一點是只能由父類對象轉換為子類對象,否則會報錯。
⑤flatMapIterable操作符
flatMapIterable操作符使用的代碼如下所示:
//將數據集合轉換為Iterable,在Iterable中對數據進行處理Observable.just(1,2,3).flatMapIterable(newFunc1>() {@OverridepublicIterablecall(Integer number){? ? ? ? ? ? ? ? ? ArrayList mList =newArrayList<>();? ? ? ? ? ? ? ? ? mList.add(1000+ number);returnmList;? ? ? ? ? ? ? }? ? ? ? ? }).subscribe(onNextAction);
flatMapIterable相當于是flatMap的變體,直接在內部以Iterable接口將集合數據進行接收,示意圖如下所示:
圖2.2.5 flatMapIterable示意圖
⑥buffer操作符
buffer操作符使用的代碼如下所示:
//buffer操作符,將原有Observable轉換為一個新的Observable,這個新的Observable每次發送一組值,而不是一個個進行發送Observable.just(1,2,3,4,5,6)? ? ? ? ? ? ? .buffer(3).subscribe(newAction1>() {@Overridepublicvoidcall(List mList){for(Integer i : mList) {? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(getActivity(),"new Number i is:"+ i, Toast.LENGTH_SHORT).show();? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? Toast.makeText(getActivity(),"Another request is called", Toast.LENGTH_SHORT).show();? ? ? ? ? ? ? ? }? ? ? ? ? ? });
buffer操作符將原有Observable轉換為一個新的Observable,這個新的Observable每次發送一組值,而不是一個個進行發送,我們可以定義這個新的Observable存放幾個原有的Observable對象。
圖2.2.6 buffer操作符示意圖
⑦groupBy操作符
groupBy操作符使用的代碼如下所示:
//groupBy操作符,可以做分組操作Observable.range(0,10).groupBy(newFunc1() {@OverridepublicIntegercall(Integer num){returnnum %3;? ? ? ? ? ? ? ? ? }? ? ? ? ? ? }).subscribe(newAction1>() {@Overridepublicvoidcall(finalGroupedObservable groupedObservable){? ? ? ? ? ? ? ? ? groupedObservable.subscribe(newAction1() {@Overridepublicvoidcall(Integer num){? ? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(getActivity(),"當前的組別是:"+ groupedObservable.getKey() +"組別內的數字是:"+ num, Toast.LENGTH_SHORT).show();? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? });? ? ? ? ? ? ? }? ? ? ? ? });
groupBy操作符,將原有的Observable對象轉換為發送一組Observable集合的GroupedObservable對象,可以做分組操作,GroupedObservable將分組完畢的Observable對象可以繼續發送。
注意:groupBy將原始Observable分解為一個發射多個GroupedObservable的Observable,一旦有訂閱,每個GroupedObservable就開始緩存數據。因此,如果你忽略這些GroupedObservable中的任何一個,這個緩存可能形成一個潛在的內存泄露。因此,如果你不想觀察,也不要忽略GroupedObservable。你應該使用像take(0)這樣會丟棄自己的緩存的操作符。
3、過濾操作符
過濾操作符用于從Observable發射的數據中進行選擇,在這里介紹如下圖所示的8種。
圖3.1 過濾操作符的分類
①filter操作符
filter操作符使用的代碼如下所示:
//filter過濾操作符,對Observable發送的內容根據自定義的規則進行過濾Observable.range(0,5).filter(newFunc1() {@OverridepublicBooleancall(Integer num){returnnum >2;//自定義的條件,只有符合條件的結果才會提交給觀察者}? ? ? ? ? }).subscribe(onNextAction);
filter默認不在任何特定的調度器上執行。
②elementAt操作符
elementAt操作符使用的代碼如下所示:
//elementAt操作符,用于返回指定位置后一位的數據,即腳標+1的數據//在這里發送0、1、2、3、4,腳標為3的數據為2,發送其后一位數據3Observable.range(0,5).elementAt(3).subscribe(onNextAction);
elementAt操作符獲取原始Observable發射的數據序列指定索引位置的數據項,然后當做自己的唯一數據發射。對應示意圖如下:
圖2.3.2 elementAt操作符示意圖
③distinct操作符
distinct操作符使用的代碼如下所示:
//distinct操作符,用于Observable發送的元素的去重Observable.just(1,1,2,2,2,3).distinct().subscribe(onNextAction);
在這里需要強調一點:distinct操作符只允許還沒有發射過的數據項通過。
④skip操作符
skip操作符使用的代碼如下所示:
//skip操作符,用于Observable發送的元素前N項去除掉Observable.range(0,5).skip(2).subscribe(onNextAction);
skip操作符抑制Observable發射的前N項數據,只發送后N項數據
圖2.3.4 skip操作符示意圖
⑤take操作符
//take操作符,用于Observable發送的元素只取前N項Observable.range(0,5).take(2).subscribe(onNextAction);
圖2.3.5 take操作符示意圖
⑥ignoreElements操作符
//ignoreElements操作符,忽略掉源Observable發送的結果,只把Observable的onCompleted或onError發送Observable.range(0,5).ignoreElements().subscribe(onNextAction, onErrorAction, onCompletedAction);
IgnoreElements操作符抑制原始Observable發射的所有數據,只允許它的終止通知(onError或onCompleted)進行發送。
⑦throttleFirst操作符
//throttleFirst操作符,會定期發送這個時間段里源Observable發送的第一個數據//throttleFirst操作符默認在computaioin調度器上執行,其他的數據都會被過濾掉Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =0; i <10; i++) {? ? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(i);//線程休眠100毫秒try{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(100);? ? ? ? ? ? ? ? ? ? ? ? ? ? }catch(InterruptedException e) {? ? ? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? }? ? ? ? ? })? ? ? ? ? .throttleFirst(200, TimeUnit.MILLISECONDS)? ? ? ? ? .subscribe(onNextAction);
throttleFirst操作符會按照固定的時間間隔將信息進行發送。在這里我設置的事件間隔為200毫秒,其中每發送一個數據線程休眠100毫秒,所以最后會顯示的數據為0,示意圖如下:
圖2..3.7 throttleFirst操作符示意圖
注:throttleFirst操作符默認在computation調度器上執行,但是你可以使用第三個參數指定其它的調度器。
⑧throttleWithTimeOut操作符
//throttleWithTimeout操作符//源發射數據時,如果兩次數據的發射間隔小于指定時間,就會丟棄前一次的數據,直到指定時間內都沒有新數據發射時才進行發射? ? ? ? ? Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(1);try{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(500);? ? ? ? ? ? ? ? ? ? ? ? ? }catch(InterruptedException e) {throwExceptions.propagate(e);? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(2);try{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(500);? ? ? ? ? ? ? ? ? ? ? ? ? }catch(InterruptedException e) {throwExceptions.propagate(e);? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(3);try{? ? ? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(1000);? ? ? ? ? ? ? ? ? ? ? ? ? }catch(InterruptedException e) {throwExceptions.propagate(e);? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(4);? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(5);? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onCompleted();? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? })? ? ? ? ? ? ? ? .throttleWithTimeout(800, TimeUnit.MILLISECONDS)? ? ? ? ? ? ? ? .subscribeOn(Schedulers.newThread())? ? ? ? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())? ? ? ? ? ? ? ? .subscribe(onNextAction);
在這里,我設置的時間間隔指定為800毫秒,所以最后顯示的數據是有3、4、5。
4、組合操作符
組合操作符用于將多個Observable組合成一個單一的Observable,在這里我介紹如下圖所示5種操作符:
圖4.1 組合操作符分類
①startWith組合操作符
startWith組合操作符使用的代碼如下所示:
//startWith操作符,會在發送的數據之前插入數據Observable.range(3,5).startWith(0,10086).subscribe(onNextAction);
很簡單,會在發送的數據序列前插入數據序列,并且會發送插入的數據序列。
②merge組合操作符
merge組合操作符使用的代碼如下所示:
//merge操作符,會將多個Observable對象合并到一個Observable對象中進行發送? ? ? ? ? ? ? ? ObservablefirstObservable = Observable.just(0, 1, 2).subscribeOn(Schedulers.io());? ? ? ? ? ? ? ? ObservablesecondObservable = Observable.just(3, 4, 5);? ? ? ? ? ? ? ? Observable.merge(firstObservable, secondObservable).subscribe(onNextAction, onErrorAction);
如下圖所示,merge操作符會將多個Observable對象進行合并。
圖2.4.2 merge操作符示意圖
需要注意的是:merge可能會讓合并的Observables發射的數據交錯。
在這里我將firstObservable指定在IO線程中進行發送,secondObservable沒有指定線程,兩者合并然后發送數據時便會產生數據交錯的現象。
③concat組合操作符
concat組合操作符使用的代碼如下所示:
//concat操作符,會將多個Observable對象合并到一個Observable對象中進行發送,嚴格按照順序進行發送? ? ? ? ? ? ? ? ObservablefirstObservable = Observable.just(0, 1, 2).subscribeOn(Schedulers.io());? ? ? ? ? ? ? ? ObservablesecondObservable = Observable.just(3, 4, 5);? ? ? ? ? ? ? ? Observable.concat(firstObservable, secondObservable)? ? ? ? ? ? ? ? ? ? ? ? .subscribeOn(Schedulers.io())? ? ? ? ? ? ? ? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())? ? ? ? ? ? ? ? ? ? ? ? .subscribe(onNextAction);
concat操作符不同于merge操作符的區別就是:會將多個Observable對象合并到一個Observable對象中進行發送,嚴格按照順序進行發送。如下圖所示,直到第一個Observable發送完畢數據后,第二個Observable才會進行數據的發送。
圖2.4.3 concat組合操作符
④zip組合操作符
zip組合操作符使用的代碼如下所示:
//zip操作符,會將多個Observable對象轉換成一個Observable對象然后進行發送,轉換關系可根據需求自定義Observable integerObservable = Observable.range(0,4);? ? ? ? ? ? ? ? Observable stringObservable = Observable.just("a","b","c","d");? ? ? ? ? ? ? ? Observable.zip(integerObservable, stringObservable,newFunc2() {? ? ? ? ? ? ? ? ? ? @Override? ? ? ? ? ? ? ? ? ? publicStringcall(Integer num,Stringinfo) {//在這里的轉換關系為將數字與字串內容進行拼接return"數字為:"+ num +"……字符為:"+ info;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).subscribe(onNextAction);
image.png
zip操作符返回一個Obversable,它使用這個函數按順序結合兩個或多個Observables發射的數據項,然后它發射這個函數返回的結果。
它按照嚴格的順序進行數據發送。它只發射與發射數據項最少的那個Observable一樣多的數據。
⑤combineLastest組合操作符
combineLastest組合操作符使用的代碼如下所示:
//combineLastest操作符,會將多個Observable對象轉換一個Observable對象然后進行發送,轉換關系可以根據需求自定義//不同于zip操作符的是,會將最新發送的數據組合到一起integerObservable = Observable.just(1,2,3);? ? ? ? ? ? ? ? stringObservable = Observable.just("a","b","c");? ? ? ? ? ? ? ? Observable.combineLatest(integerObservable, stringObservable,newFunc2() {? ? ? ? ? ? ? ? ? ? @Override? ? ? ? ? ? ? ? ? ? publicStringcall(Integer num,Stringinfo) {//在這里的轉換關系為將數字與字串內容進行拼接return"數字為:"+ num +"……字符為:"+ info;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).subscribe(onNextAction);
當兩個Observables中的任何一個發射了數據時,使用一個函數結合每個Observable發射的最近數據項,并且基于這個函數的結果發射數據。可在本案例代碼中進行驗證。
5、輔助操作符
輔助操作符就是處理Observable的幫助動作,在這里介紹如下5種輔助操作符。
圖2.5 輔助操作符分類
①delay操作符
delay操作符使用的代碼如下所示:
//delay操作符可以讓源Observable對象發送數據之前暫停一段制定的時間Observable.just(1,2,3)? ? ? ? ? ? ? ? ? ? ? ? ? .delay(2, TimeUnit.SECONDS)? ? ? ? ? ? ? ? ? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())? ? ? ? ? ? ? ? ? ? ? ? ? .subscribe(onNextAction);
在這里我將延時時間設置為2秒,延遲指定的時間后發射源Observable中的數據。
②do操作符
do操作符使用的代碼如下所示:
//doOnNext是do操作符中的一種? ? ? ? ? ? ? ? Observable.range(0, 3).doOnNext(onNextAction).subscribe(onNextAction);
do操作符,其下細分有很多內容,以doOnNext為例,其作用就是為源Observable對象發送數據后,當Subscriber接收到數據時,即當Subscriber的onNext方法被調用時,提供回調相應數據。
③subscribeOn輔助操作符
④observeOn輔助操作符
subscribeOn、observeOn操作符使用的代碼如下所示:
Observable.just("當前的線程ID為" +Thread.currentThread().getName()).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(onNextAction);
subscribeOn操作符,指定subscribe()所發生的線程,即Observable.OnSubscribe被激活時所處的線程。或者叫做事件產生的線程。
observeOn操作符,指定Subscriber所運行的線程。或者叫做事件消費的線程。
上篇文章中我提到Schedulers可以使得RxJava實現線程切換,實質上就是借助于lift變換方法進行轉換,subscribeOn發生在下圖的通知過程,observeOn發生在下圖中的發送過程。
圖2.5.4 Observable與Subscriber的轉換關系圖
⑤timeout輔助操作符
timeout操作符使用的代碼如下所示:
//timeout操作符,如果源Observable對象過了一段時間沒有發送數據,timeout會以onError通知終止這個ObservableObservable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =0; i <5; i++) {try{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(i *100);? ? ? ? ? ? ? ? ? ? ? ? ? ? }catch(InterruptedException e) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(i);? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).timeout(200, TimeUnit.MILLISECONDS, Observable.just(100,200))? ? ? ? ? ? ? ? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())? ? ? ? ? ? ? ? ? ? ? ? .subscribe(onNextAction);
需要強調的一點是,在這里timeout(long timeout, TimeUnit timeUnit, Observable other)是timeout其中的一種,它在超時的時候會將源Observable轉換為備用的Observable對象進行發送。
6、錯誤操作符
圖2.6 錯誤操作符的分類
①catch操作符
實質上在這里catch操作符細分有三種實現方案:onErrorReturn、onErrorResumeNext、onExceptionResumeNext。
首先分析onErrorReturn的代碼:
Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =0; i <5; i++) {if(i >3) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onError(newThrowable("User Alex Defined Error"));? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(i);? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).onErrorReturn(newFunc1() {@OverridepublicIntegercall(Throwable throwable){return404;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).subscribe(onNextAction, onErrorAction, onCompletedAction);
onErrorReturn操作符,會在遇到錯誤時,停止源Observable的,并調用用戶自定義的返回請求,實質上就是調用一次OnNext方法進行內容發送后,停止消息發送。
然后分析onErrorResumeNext的代碼:
Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =0; i <5; i++) {if(i >3) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onError(newThrowable("User Alex Defined Error"));? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(i);? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).onErrorResumeNext(newFunc1>() {@OverridepublicObservable call(Throwable throwable) {returnObservable.just(100,101,102);? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).subscribe(onNextAction,onErrorAction,onCompletedAction);
onErrorResumeNext操作符,會在源Observable遇到錯誤時,立即停止源Observable的數據發送,并取用新的Observable對象進行新的數據發送。
最后,分析onExceptionResumeNext的代碼:
Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =0; i <5; i++) {if(i >3) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onError(newThrowable("User Alex Defined Error"));? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(i);? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).onExceptionResumeNext(Observable.just(100,101,102)).subscribe(onNextAction,onErrorAction,onCompletedAction);
onExceptionResumeNext,會將錯誤發給Observer,而不會調用備用的Observable
②retry操作符
retry操作符實現的代碼如下所示:
//retry操作符,當遇到exception時會進行重試,重試次數可以由用戶進行定義Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =0; i <5; i++) {if(i >1) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onError(newThrowable("User Alex Defined Error"));? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? subscriber.onNext(i);? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).retry(2).subscribe(onNextAction,onErrorAction,onCompletedAction);
retry操作符不會將原始Observable的onError通知傳遞給觀察者,它會重新訂閱這個Observable。
圖2.6.2 retry操作符示意圖
7、布爾操作符
布爾操作符根據給定規則進行判斷,是否符合規則然后返回布爾值。布爾操作符意義簡單操作簡便在這里介紹如下5種:
圖2.7 布爾操作符分類
①all操作符
all操作符實現的代碼如下所示:
Observable.just(1,2,3,4).all(newFunc1() {@OverridepublicBooleancall(Integer num){returnnum >3;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).subscribe(onNextAction, onErrorAction, onCompletedAction);
all操作符,對源Observable發送的每一個數據根據給定的條件進行判斷。如果全部符合條件,返回true,否則返回false。
②contains操作符
contains操作符實現的代碼如下所示:
Observable.just(1, 2, 3, 4).contains(2).subscribe(onNextAction,onErrorAction,onCompletedAction);
contains操作符,對源Observable發送的數據是否包含定義的選項進行判斷。如果包含返回true,否則返回false。
③isEmpty操作符
isEmpty操作符實現的代碼如下所示:
Observable.just(1, 2, 3, 4).isEmpty().subscribe(onNextAction,onErrorAction,onCompletedAction);
isEmpty操作符,對源Observable發送的數據是否為空進行判斷。如果源Observable發送的數據為空返回true,否則返回false。
④exists操作符
exists操作符實現的代碼如下所示:
Observable.just(1,2,3,4).exists(newFunc1() {@OverridepublicBooleancall(Integer num){returnnum >3;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).subscribe(onNextAction, onErrorAction, onCompletedAction);
exists操作符,對源Observable發送的單獨一個數據根據給定的條件進行判斷。如果有一個數據符合條件,返回true,否則返回false。
⑤sequenceEqual操作符
sequenceEqual操作符實現的代碼如下所示:
Observable.sequenceEqual(Observable.just(1, 2, 3, 4),Observable.just(1)).subscribe(onNextAction,onErrorAction,onCompletedAction);
sequenceEqual操作符,對兩個Observable進行判斷,兩個Observable相同時返回true,否則返回false。這里包含兩個Observable的數據,發射順序,終止狀態是否相同。
8、條件操作符
圖2.8 條件操作符
①amb操作符
amb操作符實現的代碼如下所示:
//給定多個Observable,只讓第一個發送數據的Observable發送數據Observable? ? ? ? ? ? ? ? ? ? ? ? .amb(Observable.range(0,3).delay(2000, TimeUnit.MILLISECONDS),Observable.range(100,3))? ? ? ? ? ? ? ? ? ? ? ? .subscribe(onNextAction);
如下圖所示,首先發送通知給Amb的那個,不管發射的是一項數據還是一個onError或onCompleted通知。Amb將忽略和丟棄其它所有Observables的發射物。
圖2.8.1 amb操作符示意圖
②defaultIfEmpty操作符
amb操作符實現的代碼如下所示:
//如果源Observable沒有發送數據,則發送一個默認數據Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){? ? ? ? ? ? ? ? ? ? ? ? subscriber.onCompleted();? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }).defaultIfEmpty(404).subscribe(onNextAction,onErrorAction,onCompletedAction);
9、轉換操作符
轉換操作符可以將Observable轉換為其它的對象或數據結構。在這里介紹如下所示三種轉換操作符:
圖2.9 轉換操作符的分類
①toList操作符
toList操作符實現的代碼如下所示:
//toList操作符,將源Observable發送的數據組合為一個List集合//然后再次在onNext方法中將轉換完的List集合進行傳遞Observable.just(1,2,3).toList().subscribe(newAction1>() {@Overridepublicvoidcall(List numList){for(Integer i : numList) {? ? ? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(getActivity(),"i:"+ i, Toast.LENGTH_SHORT).show();? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? });
通常,發射多項數據的Observable會為每一項數據調用onNext方法。你可以用toList操作符改變這個行為,讓Observable將多項數據組合成一個List,然后調用一次onNext方法傳遞整個列表。
②toSortedList操作符
toSortedList操作符實現的代碼如下所示:
//toSortedList操作符,會將源Observable發送的數據組合為一個List集合,并會按照升序的方式進行排序//然后再次在onNext方法中將轉換完的List集合進行傳遞Observable.just(40,10,80,30).toSortedList().subscribe(newAction1>() {@Overridepublicvoidcall(List numList){for(Integer i : numList) {? ? ? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(getActivity(),"i:"+ i, Toast.LENGTH_SHORT).show();? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? });
不同于toList操作符的是,它會對產生的列表排序,默認是自然升序。
③toMap操作符
toMap操作符實現的代碼如下所示:
//toMap操作符,將源Observable發送的數據作為Map集合中的值,需要值進行鍵的定義//將轉換完畢的Map集合在onNext方法中進行發送Observable.just("Alex","Payne").toMap(newFunc1() {@OverridepublicIntegercall(String s){returns.equals("Alex")?0:1;? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? }).subscribe(newAction1>() {@Overridepublicvoidcall(Map convertMap){for(inti =0; i < convertMap.size(); i++) {? ? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(getActivity(), convertMap.get(i), Toast.LENGTH_SHORT).show();? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? });
源Observable發送的數據作為鍵值對中的值,我們可以提供一個用于生成Map的Key的函數,然后不同的鍵存儲源Observable發送的不同的值。
toMap默認不在任何特定的調度器上執行。
圖2.9.3 toMap操作符示意圖
三、總結
1、在本文中,我結合項目代碼詳細介紹了部分RxJava的操作符,局部參照:RxJava中文翻譯文檔。
2、本文中的案例代碼已上傳Github,歡迎大家star、fork。詳情戳→GitHub案例代碼。
3、操作符實質上就是RxJava函數式編程模式的體現,Lambda表達式并且可以進一步優化RxJava。
4、在下篇文章中我會對于RxJava進行深層次的剖析,還有RxJava結合例如Retrofit、RxBus等開源框架的內容,希望本文對你在學習RxJava的路上有所啟發。
小禮物走一走,來簡書關注我
作者:Alex_Payne
鏈接:http://www.lxweimin.com/p/d997805b37d4
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。