前言
由於公司重新規劃的部門,我調到了另外一個部門,所以負責的專案也換了,仔細看了下整體的專案,rxjava+retrofit。整體的一套。眾所周知,rxjava+retrofit是目前網上最流行的網路解析框架。而目前網路上的文章大多還是關於rxjava1的。關於RxJava2的少之又少,於是,便有了此文。
此文的目的有三個: 1. 給對 RxJava2感興趣的人一些入門的指引 2. 給正在使用 RxJava2但仍然心存疑惑的人一些更深入的解析 3.給想從RxJava1替換成RxJava2的人給出直接的對比。
RxJava概念介紹
RxJava=reactive+extension。 那麼接下來我會分別對這兩點進行整體的介紹。reactive又稱reactive programming。也就是響應式程式設計。在往簡單的說,rxjava可以很方便的處理執行緒切換的問題。說到這個,我們就會想到非同步操作。handler?AsyncTask?但你要知道,隨著請求的數量越來越多,程式碼邏輯將會變得越來越複雜。而rxjava卻仍可以保持清晰的邏輯。它的原理就是建立一個Observable物件來搞事情。然後使用各種操作符通過建造者模式建立成一系列的鏈式操作。就如流水線一樣,把事情搞完。然後發射給Observer進行處理。
觀察者模式
rxjava的實現主要是通過觀察者模式實現的。那麼什麼是觀察者模式,我這邊做一個簡單的介紹。
栗子:觀察者對被觀察者進行一個簡單,當被觀察者被改變時,要立即做出反應。比如,你認為隔壁老王和你媳婦有一腿,但卻沒證據,此時,只要當隔壁老王進了你媳婦房門的時候,你就要去捕獲他。在這個例子中,你是觀察者,老王是被觀察者。(記得當初我經常搞反了)。那麼,觀察者模式是否是一對一呢?很明顯不是的,就上面的例子,你可以叫三千城管監聽著老王。只要他有不軌之心。就打斷他的第三條腿。也就是說多個觀察者對應一個被觀察者。字看累了來看圖:
其實在android中也有很多自帶的觀察者模式。最明顯的莫過於點選事件。說個最簡單的例子,點選按鈕後彈一個吐司。那麼,我們在點選按鈕的時候,告知系統,此時,我需要彈一個吐司。那麼就這麼彈出來了。那麼,這個時候問題來了。我是否需要實時去監聽這個按鈕呢?答案是不需要的。這就和前面的舉例有的差距了。換句話說。我只要在此按鈕進行點選時進行監聽就可以了。這種操作被稱為訂閱。也就是說Button通過setOnClickListener對OnclickListener進行了訂閱了操作,來監聽onclick方法。
extension
不僅支援事件序列,還支援資料流。事件-->動態的,無法預知,例如:事件點選,伺服器的推送等等 資料流-->靜態的,可預知的,例如:讀取本地檔案,播放音視訊等等。
通過操作符對中間事件的處理。
執行緒操作的便捷。關於這些具體的實現。我會在後面一一舉例。
RxJava1與RxJava2的區別
說到區別,可能有的小夥伴會問,我沒看過rxjava1。可以直接看rxjava2麼。個人覺得不必要,因為 rxjava2.x 是按照 Reactive-Streams specification 規範完全的重寫的,完全獨立於 rxjava1.x 而存在,它改變了以往 rxjava1的用法。換句話說,我學java需不需要先學C語言一樣。
那麼兩者的區別體現在哪呢?主要是如下幾個方面:
空指標問題這應該是一個很大的變化,用過rxjava1的人都知道,我們可以在發射事件的時候傳入NULL。但這在rxjava2中是不存在的。不信你試試?分分鐘給你來一個NullPointerExpection。
Function相關的在rxjava1中,我們有各種Func1,Func2......,但在rxjava2中只有Function了。依舊記得看凱哥的文章的時候把我整蒙了。愣是沒發現,後來才注意到被替換了。並且,他們都增加了throw exception。
背壓—backpressure 關於backpressure,這個就厲害了。厲害到我都不懂了。好了,開個玩笑,我們繼續說。我們知道在Rxjava1中Observable對backpressure是支援的。但在Rxjava2中Observable取消了對backpressure的支援。並且引進了一個叫做Flowable的來支援backpressure。
那麼什麼是背壓: 聽不懂的含義:上游的生產速度大於下游的處理速度,導致下游處理不急,這種操作被稱為backpressure。
這種情況看似很常見,但實際上,這種情況並不常見,或者可以說成非常罕見。那麼遇到了怎麼辦?如果它出現了,直接丟棄。what the fuck?你tm在逗我?但事實就是這樣,如果我們在開發過程中,遇到了backpressure,我們就應該丟棄它。
聽得懂的含義:對於可丟棄的事件,上游生產速度過快導致事件堆積,當堆積到超出buffer上限的時候,就叫做backpressure。
處理方案是什麼: 1、丟棄新事件;2、不丟棄,繼續堆積。(忽略了backpressure,相當於Observable)。
適合backpressure的情況: 線上直播流:比如說,正在直播的時候,突然網路出現了卡頓,頁面卡住了。那麼當網路好了之後肯定不會是在接著之前的頁面繼續的,就相當於,你網路卡了多久,他就丟棄了多長時間的資料。
backpressure的關鍵點是什麼:不可控,可丟棄。
基本使用
講了一大堆理念知識,接下來就是開工幹活了。那麼關於Rxjava2的基本實現主要是三點:建立Observable,建立Observer,進行繫結。那麼我們一個個的看。
建立Observable
Observable是什麼?觀察者還是被觀察者?我又忘了。哈哈。開個玩笑,當然是後者了。為什麼是先建立Observable而不是Observer?當然了,先後順序的無所謂的。但是考慮到後面的鏈式呼叫。所以我這邊就先寫了先建立Observable了。
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("Hello");
emitter.onNext("Rxjava2");
emitter.onNext("My name is Silence");
emitter.onNext("What's your name");
//一旦呼叫onComplete,下面將不在接受事件
emitter.onComplete();
}
});複製程式碼
現在我來解釋一下上面的ObservableEmitter到底是什麼。字面意思是可觀察的發射器。沒錯,這個就是被觀察者用來傳送事件的。它可以發出三種型別的事件,通過呼叫emitter的onNext(T value)、onError(Throwable error)和onComplete()就可以分別發出next事件、error事件和complete事件。至於這三個事件到底什麼意思。不急,我們後面說。
建立Observer
現在我們來建立一個觀察者,它決定了在觀察中到底應該有著什麼樣的行為操作。
Observer<String> observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i(TAG, "onSubscribe: " + d);
result += "onSubscribe: " + d + "\n";
}
@Override
public void onNext(String string) {
Log.i(TAG, "onNext: " + string);
result += "onNext: " + string + "\n";
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError: " + e);
result += "onError: " + e + "\n";
}
@Override
public void onComplete() {
Log.i(TAG, "onComplete: ");
result += "onComplete: " + "\n";
}
};複製程式碼
其中onSubscribe、onNext、onError和onComplete是必要的實現方法,其含義如下:
onSubscribe:它會在事件還未傳送之前被呼叫,可以用來做一些準備操作。而裡面的Disposable則是用來切斷上下游的關係的。
onNext:普通的事件。將要處理的事件新增到佇列中。
onError:事件佇列異常,在事件處理過程中出現異常情況時,此方法會被呼叫。同時佇列將會終止,也就是不允許在有事件發出。
onComplete:事件佇列完成。rxjava不僅把每個事件單獨處理。而且會把他們當成一個佇列。當不再有onNext事件發出時,需要觸發onComplete方法作為完成標識。
進行Subscribe
訂閱其實只需要一行程式碼就夠了:
observerable.subscribe(Observer);複製程式碼
執行一個看看效果先:
和之前介紹的一樣,先呼叫onSubscribe,然後走了onNext,最後以onComplete收尾。
神奇的操作符
對於rxjava來說,有一句話,我覺得說的很對,叫做:如果你每天研究一個操作符,最少一個半月,如果你想理解原理。最少半年。換句話說,有關rxjava的知識完全可以寫一本書。那麼本文肯定不會講那麼細。在這邊我會給你們介紹一些常用的操作符。保證日常開發的流程足矣。
建立操作符
一般建立操作符是指,剛開始建立觀察者的時候呼叫的。在基本使用中我已經介紹了create操作符,那麼這邊我們就要說到just,fromarray和interval了。
just
此操作符是將傳入的引數依次發出來。
Observable observable = Observable.just("Hello", "Rxjava2", "My name is Silence","What's your name");
// 將會依次呼叫:
// onNext("Hello");
// onNext("Rxjava2");
// onNext("My name is Silence");
// onNext("What's your name");
// onCompleted();複製程式碼
fromarray
將傳入的陣列通過座標一次傳送出去。
String[] words = {"Hello", "Rxjava2", "My name is Silence","What's your name"};
Observable observable = Observable.from(words);
// 將會依次呼叫:
// onNext("Hello");
// onNext("Rxjava2");
// onNext("My name is Silence");
// onNext("What's your name");
// onCompleted();複製程式碼
interval
這個其實就是定時器,用了它你可以拋棄CountDownTimer了。現在我們看看怎麼用:
Observable.interval(2, TimeUnit.SECONDS).subscribe(
new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.i(TAG, "accept: "+aLong.intValue());
}
}
);複製程式碼
我們看看結果:
上面就是我們每隔2s列印一次long的值。
變換操作符
變換操作符的作用是對Observable發射的資料按照一定規則做一些變換操作,然後講變換後的資料發射出去。變換操作符有map,flatMap,concatMap,switchMap,buffer,groupBy等等。這裡我們會講解最常用的map,flatMap、concatMap以及compose。
map
map操作符通過指定一個Function物件,將Observable轉換為一個新的Observable物件併發射,觀察者將收到新的Observable處理。直接上程式碼:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onNext(4);
}
}).map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
return "This is result " + integer + "\n";
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String str) throws Exception {
Log.i("--->", "accept: "+str);
string += str;
}
});
tv_first.setText(string);複製程式碼
輸入結果如下:
仔細看,map()方法中,我們把一個integer物件轉換成了一個String物件。然後當map()呼叫結束時,事件的引數型別也從integer轉換成了String。這就是最常見的變換操作。
flatMap
flatmap的操作符是將Observable發射的資料集合變成一個Observable集合。也就是說它可以講一個觀察物件變換成多個觀察物件,但是並不能保證事件的順序。想保證事件的順序?那你過會看下面降到的concatMap。
那麼什麼叫作資料集合變成一個Observable集合呢?還是用上面的例子,我有一組integer集合。我想轉換成string集合怎麼辦?那就繼續看程式碼:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
}).flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
final List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("I am value " + integer + "\n");
}
return Observable.fromIterable(list);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i("--->", "accept: "+s);
string += s;
}
});
tv_first.setText(string);複製程式碼
我們來看結果:
打住打住,是不是有問題?WTF?有啥問題?還記不記得我上面說過flatMap不能保證事件執行順序。那麼這邊事件為什麼都是按順序執行的?不急,我們在發射事件的時候給他加一個延遲在看看結果:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
}).flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
final List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("I am value " + integer + "\n");
}
return Observable.fromIterable(list).delay(100,TimeUnit.MILLISECONDS);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i("--->", "accept: "+s);
string += s;
}
});
tv_first.setText(string);複製程式碼
我們在當他發射事件的時候給他加一個100ms的延遲看看結果:
看到沒有,我說啥的?不能保證執行順序。所以萬事容我慢慢道來。先喝杯茶壓壓驚。我們在接著往下講。
concatMap
上面我也介紹了concatMap。除了保證了執行順序,其他都和concatMap一毛一樣。你說保證就保證啊。您先喝杯茶,接著往下看:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
}).concatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
final List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("I am value " + integer + "\n");
}
return Observable.fromIterable(list).delay(1000,TimeUnit.MILLISECONDS);
// return Observable.fromIterable(list);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i("--->", "accept: "+s);
string += s;
}
});
tv_first.setText(string);複製程式碼
為了我們能看的更明顯一點,我這邊直接設定了一秒鐘的延遲。下面我們來看效果圖:
可以從執行順序和列印時間看出,的的確確是延遲了一秒鐘。
compose
這個操作符就很厲害了。他的變換是怎麼做的呢?我們知道rxjava是通過建造者的模式通過鏈式來呼叫起來的。那麼多個鏈式就需要多個Observable。而這個操作符就是把多個Observable轉化成一個Observable。聽起來是不是很厲害~。具體如何操作,我們接著看:
public <T> ObservableTransformer<T, T> applyObservableAsync() {
return new ObservableTransformer<T, T>() {
@Override
public ObservableSource<T> apply(Observable<T> upstream) {
return upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}複製程式碼
上面程式碼可以看出,我把子執行緒和主執行緒進行了一個封裝,然後返回了一個ObservableTransformer物件。那麼我們只要這邊做就可以了:
Observable.just(1, 2, 3, 4, 5, 6)
.compose(this.<Integer>applyObservableAsync())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer strings) throws Exception {
Log.i("-->", "accept: " + strings);
string += strings;
}
});
tv_first.setText(string);複製程式碼
過濾操作符
過濾操作符用於過濾和選擇Observable發射的資料序列。讓Observable只返回滿足我們條件的資料。過濾操作符有buffer,filter,skip,take,skipLast,takeLast等等,這邊我會介紹到filter,buffer,skip,take,distinct。
filter
filter操作符是對源Observable產生的結果進行有規則的過濾。只有滿足規則的結果才會提交到觀察者手中。例如:
Observable.just(1,2,3).filter(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) throws Exception {
return integer < 3;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer s) throws Exception {
Log.i("--->", "accept: " + s);
string += s;
}
});
tv_first.setText(string);
}複製程式碼
程式碼很簡單,我們傳送1,2,3;但是我們加上一個filter操作符,讓它只返回小於3的的內容。那麼我們來看一下結果:
distinct
這個操作符其實就更簡單了。比如說,我要在一組資料中去掉重複的內容,就要用到它。也就是去重。它只允許還沒有發射的資料項通過。發射過的資料項直接pass。
Observable.just(1,2,3,4,2,3,5,6,1,3)
.distinct().subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer s) throws Exception {
Log.i("--->", "accept: " + s);
string += s;
}
});
tv_first.setText(string);複製程式碼
那麼輸出結果就很簡單了:
buffer
這個其實也不難,主要是快取,把源Observable轉換成一個新的Observable。這個新的Observable每次發射的是一組List,而不是單獨的一個個的傳送資料來源。
Observable.just(1,2,3,4,5,6)
.buffer(2).subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> strings) throws Exception {
for (Integer integer : strings) {
Log.i("-->", "accept: "+integer);
string+=strings;
}
Log.i("-->", "accept: ----------------------->");
}
});
tv_first.setText(string);複製程式碼
我們讓他每次快取2個,下面我們來看結果:
skip 、take
skip操作符將源Observable發射過的資料過濾掉前n項,而take操作則只取前n項;另外還有skipLast和takeLast則是從後往前進行過濾。先來看看skip操作符。
Observable.just(1, 2, 3, 4, 5, 6)
.skip(2).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer strings) throws Exception {
Log.i("-->", "accept: " + strings);
string += strings;
}
});
tv_first.setText(string);複製程式碼
結果如下:
接下來我們把skip換成take看看。
Observable.just(1, 2, 3, 4, 5, 6)
.take(3).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer strings) throws Exception {
Log.i("-->", "accept: " + strings);
string += strings;
}
});
tv_first.setText(string);複製程式碼
結果如下:
組合操作符
merge
merge是將多個操作符合併到一個Observable中進行發射,merge可能讓合併到Observable的資料發生錯亂。(並行無序)
Observable<Integer> observable1=Observable.just(1,2,3);
Observable<Integer> observable2=Observable.just(1,2,3);
Observable.merge(observable1,observable2).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "accept: "+integer);
}
});複製程式碼
結果如下:
concat
將多個Observable發射的資料進行合併並且發射,和merge不同的是,merge是無序的,而concat是有序的。(序列有序)沒有發射完前一個它一定不會傳送後一個。
Observable<Integer> observable1=Observable.just(1,2,3);
Observable<Integer> observable2=Observable.just(4,5,6);
Observable.concat(observable1,observable2).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "accept: "+integer);
}
});複製程式碼
結果如下:
zip
此操作符和合並多個Observable傳送的資料項,根據他們的型別就行重新變換,併發射一個新的值。
Observable<Integer> observable1=Observable.just(1,2,3);
Observable<String> observable2=Observable.just("a","b","c");
Observable.zip(observable1, observable2, new BiFunction<Integer, String, String>() {
@Override
public String apply(Integer integer, String s) throws Exception {
return integer+s;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i(TAG, "apply: "+s);
}
});複製程式碼
結果如下:
concatEager
前面說道序列有序,而concatEager則是並行且有序。我們來看看如果修改:
Observable<Integer> observable1=Observable.just(1,2,3);
Observable<String> observable2=Observable.just("a","b","c");
Observable.concatEager(Observable.fromArray(observable1,observable2)).subscribe(new Consumer<Serializable>() {
@Override
public void accept(Serializable serializable) throws Exception {
Log.i(TAG, "accept: "+serializable);
}
});複製程式碼
結果如下:
執行緒控制
其實執行緒控制也是一種操作符。但它不屬於建立、變換、過濾。所以我這邊把它單獨拉出來講講。
subscribeOn是指上游傳送事件的執行緒。說白了也就是子執行緒。多次指定上游的執行緒只有第一次指定的有效, 也就是說多次呼叫subscribeOn()
只有第一次的有效, 其餘的會被忽略。
observerOn是指下游接受事件的執行緒。也就是主執行緒。多次指定下游的執行緒是可以的, 也就是說每呼叫一次observeOn()
, 下游的執行緒就會切換一次。
舉個栗子:
Observable.just(1, 2, 3, 4) // IO 執行緒,由 subscribeOn() 指定
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.map(mapOperator) // 新執行緒,由 observeOn() 指定
.observeOn(Schedulers.io())
.map(mapOperator2) // IO 執行緒,由 observeOn() 指定
.observeOn(AndroidSchedulers.mainThread)
.subscribe(subscriber); // Android 主執行緒,由 observeOn() 指定複製程式碼
在RxJava中, 已經內建了很多執行緒選項供我們選擇, 例如有
Schedulers.io()
:I/O操作(讀寫檔案、資料庫,及網路互動等)所使用的Scheduler。行為模式和newThread()差不多。區別在於io()的內部實現是用一個無數量上限的執行緒池。可以重用空閒的執行緒。因此多數情況下io()比newThread()更有效率。Schedulers.immediate()
: 直接在當前執行緒執行。Schedulers.computation()
:計算所使用的Scheduler,例如圖形的計算。這個Scheduler使用固定執行緒池,大小為CPU核數。不要把I/O操作放在computation中。否則I/O操作的等待會浪費CPU。Schedulers.newThread()
:代表一個常規的新執行緒Schedulers.trampoline()
: 當我們想線上程執行一個任務時(不是立即執行),可以用此方法將它加入佇列。這個排程器將會處理它的佇列並且按序執行佇列中的每一個任務。AndroidSchedulers.mainThread()
:代表Android的主執行緒
這些內建的Scheduler已經足夠滿足我們開發的需求, 因此我們應該使用內建的這些選項, 在RxJava內部使用的是執行緒池來維護這些執行緒, 所有效率也比較高。
與Retrofit結合
就目前開發角度而言,retrofit可以說是最火的網路框架。其原因我認為有兩點,第一:可以和okhttp結合。第二:可以和rxjava結合。也就是說Retrofit 除了提供了傳統的 Callback
形式的 API,還有 RxJava 版本的 Observable
形式 API。
如果需要使用retrofit,我們需要在gradle的配置加上這句:
compile 'com.squareup.retrofit2:retrofit:2.0.1'複製程式碼
話不多說,直接上例子:
private static OkHttpClient mOkHttpClient;
private static Converter.Factory gsonConverterFactory = GsonConverterFactory.create();
private static CallAdapter.Factory rxJavaCallAdapterFactory = RxJavaCallAdapterFactory.create();
public static BaseHttpApi getObserve() {
if (baseHttpApi == null) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(gsonConverterFactory)
.addCallAdapterFactory(rxJavaCallAdapterFactory)
.client(mOkHttpClient)
.baseUrl(BaseUrl.WEB_BASE)
.build();
baseHttpApi = retrofit.create(BaseHttpApi.class);
}
return baseHttpApi;
}複製程式碼
如上程式碼,可以很清晰的看出,它通過2個工廠模式建立了gson和rxjava。並且通過了鏈式呼叫將他們進行了繫結。那麼怎麼通過鏈式呼叫實現網路請求呢?不急,我們喝杯茶,接著往下看。
比如,一個post請求,我們可以這麼寫:
public interface BaseHttpApi{
@FormUrlEncoded
@POST("seller/cash_flow_log_detail.json")
Observable<ServiceReward> serviceReward(@Field("requestmodel") String model);
}複製程式碼
敲黑板了。注意,我這邊是interface而不是一個class。接下來就是日常呼叫了,程式碼如下:
Network.getObserve()
.serviceReward(new Gson().toJson(map))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ServiceReward>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(ServiceReward serviceReward) {
parseOrderDetail(serviceReward);
}
});複製程式碼
看第二行,這就是為什麼剛開始為什麼要用工廠模式建立gson的原因。現在我們只要在parseOrderDetail方法中處理正常的邏輯就可以了。是不是看起來程式碼有點多?那麼我們可以這樣:
Network.getObserve()
.serviceReward(new Gson().toJson(map))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(serviceReward ->{
parseOrderDetail(serviceReward);
});複製程式碼
一個lamada表示式,是不是感覺瞬間程式碼少了很多,不過有人要說,我載入的時候是一個彈窗顯示的,如果載入失敗了我這個彈窗豈不是影藏不了?不存在的,如果真有這種情況怎麼做?我們接著看:
Network.getObserve()
.serviceReward(new Gson().toJson(map))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(serviceReward ->{
parseOrderDetail(serviceReward);
},throwable ->{do something when net error...});複製程式碼
這麼處理豈不是快哉。對於lamada,剛開始可能都是各種不習慣,不過用習慣了就會發現程式碼各種簡潔(我最近也在適應中)。
最後
關於rxjava其實對我們來說很難上手。或者不能這麼說,應該是rxjava的東西太深了,我們很難掌握透徹。所以我前面也說了如果你每天研究一個操作符,最少一個半月,如果你想理解原理。最少半年。換句話說,有關rxjava的知識完全可以寫一本書。但日常開發中,此文中的內容基本可以解決大部分的日常需求。當然,如果你有心的話,你可以去嘗試著瞭解rxjava底層的實現原理。