RxJava——操作符篇

一、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

來源:簡書

簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內容

  • 一、RxJava操作符概述 RxJava中的操作符就是為了提供函數式的特性,函數式最大的好處就是使得數據處理簡潔易...
    測天測地測空氣閱讀 645評論 0 1
  • 一、RxJava操作符概述 RxJava中的操作符就是為了提供函數式的特性,函數式最大的好處就是使得數據處理簡潔易...
    王帥Alex閱讀 19,165評論 21 98
  • 作者: maplejaw本篇只解析標準包中的操作符。對于擴展包,由于使用率較低,如有需求,請讀者自行查閱文檔。 創...
    maplejaw_閱讀 45,722評論 8 93
  • 一、Retrofit詳解 ·Retrofit的官網地址為 : http://square.github.io/re...
    余生_d630閱讀 1,885評論 0 5
  • 注:只包含標準包中的操作符,用于個人學習及備忘參考博客:http://blog.csdn.net/maplejaw...
    小白要超神閱讀 2,206評論 2 8