最近項(xiàng)目中用到了異步操作,感覺(jué)android自身的AsyncTask和handler有點(diǎn)繁瑣且不夠簡(jiǎn)潔,于是學(xué)習(xí)了一下Rxjava,并沒(méi)有特別深入,但有了基本的了解
一.簡(jiǎn)介
RxJava 在 GitHub 主頁(yè)上的自我介紹是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一個(gè)在 Java VM 上使用可觀測(cè)的序列來(lái)組成異步的、基于事件的程序的庫(kù))。
RxJava 的優(yōu)勢(shì)就是簡(jiǎn)潔,但它的簡(jiǎn)潔的與眾不同之處在于,隨著程序邏輯變得越來(lái)越復(fù)雜,它依然能夠保持簡(jiǎn)潔。其原理在于,RxJava 的實(shí)現(xiàn),是一條從上到下的鏈?zhǔn)秸{(diào)用,沒(méi)有任何嵌套,這在邏輯的簡(jiǎn)潔性上是具有優(yōu)勢(shì)的。當(dāng)需求變得復(fù)雜時(shí),這種優(yōu)勢(shì)將更加明顯。
二.基本概念
Observable:發(fā)射源,英文釋義“可觀察的”,在觀察者模式中稱為“被觀察者”或“可觀察對(duì)象”;
Observer:接收源,英文釋義“觀察者”,沒(méi)錯(cuò)!就是觀察者模式中的“觀察者”,可接收Observable、Subject發(fā)射的數(shù)據(jù);
Subscriber:“訂閱者”,也是接收源,那它跟Observer有什么區(qū)別呢?Subscriber實(shí)現(xiàn)了Observer接口,比Observer多了一個(gè)最重要的方法unsubscribe( ),用來(lái)取消訂閱,當(dāng)你不再想接收數(shù)據(jù)了,可以調(diào)用unsubscribe( )方法停止接收,Observer 在 subscribe() 過(guò)程中,最終也會(huì)被轉(zhuǎn)換成 Subscriber 對(duì)象,一般情況下,建議使用Subscriber作為接收源;
Subscription :Observable調(diào)用subscribe( )方法返回的對(duì)象,同樣有unsubscribe( )方法,可以用來(lái)取消訂閱事件;
Action0:RxJava中的一個(gè)接口,它只有一個(gè)無(wú)參call()方法,且無(wú)返回值,同樣還有Action1,Action2...Action9等,Action1封裝了含有 1 個(gè)參的call()方法,即call(T t),Action2封裝了含有 2 個(gè)參數(shù)的call方法,即call(T1 t1,T2 t2),以此類推;
Func0:與Action0非常相似,也有call()方法,但是它是有返回值的,同樣也有Func0、Func1...Func9;
RxJava 的觀察者模式大致如下圖:

與傳統(tǒng)觀察者模式不同, RxJava 的事件回調(diào)方法除了普通事件 onNext() (相當(dāng)于 onClick() / onEvent())之外,還定義了兩個(gè)特殊的事件:onCompleted() 和 onError()。
- onCompleted(): 事件隊(duì)列完結(jié)。RxJava 不僅把每個(gè)事件單獨(dú)處理,還會(huì)把它們看做一個(gè)隊(duì)列。RxJava 規(guī)定,當(dāng)不會(huì)再有新的 onNext() 發(fā)出時(shí),需要觸發(fā) onCompleted() 方法作為標(biāo)志。
- onError(): 事件隊(duì)列異常。在事件處理過(guò)程中出異常時(shí),onError() 會(huì)被觸發(fā),同時(shí)隊(duì)列自動(dòng)終止,不允許再有事件發(fā)出。
- 在一個(gè)正確運(yùn)行的事件序列中, onCompleted() 和 onError() 有且只有一個(gè),并且是事件序列中的最后一個(gè)。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在隊(duì)列中調(diào)用了其中一個(gè),就不應(yīng)該再調(diào)用另一個(gè)。
三.基本用法
- 創(chuàng)建 Observer
Observer<String> observer = new Observer<String>() {
@Override
public void onNext(String s) {
Log.d(tag, "Item: " + s);
}
@Override
public void onCompleted() {
Log.d(tag, "Completed!");
}
@Override
public void onError(Throwable e) {
Log.d(tag, "Error!");
}
};```
- **創(chuàng)建 Observable**
1.使用create( )
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello");
subscriber.onCompleted();
}
});```
可以看到,這里傳入了一個(gè) OnSubscribe 對(duì)象作為參數(shù)。OnSubscribe 會(huì)被存儲(chǔ)在返回的 Observable 對(duì)象中,它的作用相當(dāng)于一個(gè)計(jì)劃表,當(dāng) Observable 被訂閱的時(shí)候,OnSubscribe 的 call() 方法會(huì)自動(dòng)被調(diào)用,事件序列就會(huì)依照設(shè)定依次觸發(fā)(對(duì)于上面的代碼,就是觀察者Subscriber 將會(huì)被調(diào)用一次 onNext() 和一次 onCompleted())。這樣,由被觀察者調(diào)用了觀察者的回調(diào)方法,就實(shí)現(xiàn)了由被觀察者向觀察者的事件傳遞,即觀察者模式。
2.使用just( ),將為你創(chuàng)建一個(gè)Observable并自動(dòng)為你調(diào)用onNext( )發(fā)射數(shù)據(jù):
justObservable = Observable.just("just1","just2");//依次發(fā)送"just1"和"just2"```
3.使用from( ),遍歷集合,發(fā)送每個(gè)item:
List<String> list = new ArrayList<>();
list.add("from1");
list.add("from2");
list.add("from3");
fromObservable = Observable.from(list); //遍歷list 每次發(fā)送一個(gè)
/** 注意,just()方法也可以傳list,但是發(fā)送的是整個(gè)list對(duì)象,而from()發(fā)送的是list的一個(gè)item** /```
- Subscribe (訂閱)
observable.subscribe(observer);
Observer的onNext方法將會(huì)依次收到來(lái)自justObservable的數(shù)據(jù),另外,如果你不在意數(shù)據(jù)是否接收完或者是否出現(xiàn)錯(cuò)誤,即不需要Observer的onCompleted()和onError()方法,可使用Action1,subscribe()支持將Action1作為參數(shù)傳入,RxJava將會(huì)調(diào)用它的call方法來(lái)接收數(shù)據(jù),代碼如下:
justObservable.subscribe(new Action1<String>() {
@Override
public void call(String s) {
...
}});```
- **線程控制 —— Scheduler **
在不指定線程的情況下, RxJava 遵循的是線程不變的原則,即:在哪個(gè)線程調(diào)用 subscribe(),就在哪個(gè)線程生產(chǎn)事件;在哪個(gè)線程生產(chǎn)事件,就在哪個(gè)線程消費(fèi)事件。如果需要切換線程,就需要用到 Scheduler (調(diào)度器)。
RxJava 已經(jīng)內(nèi)置了幾個(gè) Scheduler ,它們已經(jīng)適合大多數(shù)的使用場(chǎng)景:
- Schedulers.immediate(): 直接在當(dāng)前線程運(yùn)行,相當(dāng)于不指定線程。這是默認(rèn)的 Scheduler。
- Schedulers.newThread(): 總是啟用新線程,并在新線程執(zhí)行操作。
- Schedulers.io(): I/O 操作(讀寫文件、讀寫數(shù)據(jù)庫(kù)、網(wǎng)絡(luò)信息交互等)所使用的 Scheduler。行為模式和 newThread() 差不多,區(qū)別在于 io() 的內(nèi)部實(shí)現(xiàn)是是用一個(gè)無(wú)數(shù)量上限的線程池,可以重用空閑的線程,因此多數(shù)情況下 io() 比 newThread() 更有效率。不要把計(jì)算工作放在 io() 中,可以避免創(chuàng)建不必要的線程。
- Schedulers.computation(): 計(jì)算所使用的 Scheduler。這個(gè)計(jì)算指的是 CPU 密集型計(jì)算,即不會(huì)被 I/O 等操作限制性能的操作,例如圖形的計(jì)算。這個(gè) Scheduler 使用的固定的線程池,大小為 CPU 核數(shù)。不要把 I/O 操作放在 computation() 中,否則 I/O 操作的等待時(shí)間會(huì)浪費(fèi) CPU。
- Schedulers.mainThread(),它指定的操作將在 Android 主線程運(yùn)行。
有了這幾個(gè) Scheduler ,就可以使用 subscribeOn() 和 observeOn() 兩個(gè)方法來(lái)對(duì)線程進(jìn)行控制了。 subscribeOn(): 指定 subscribe() 所發(fā)生的線程,即 Observable.OnSubscribe 被激活時(shí)所處的線程?;蛘呓凶鍪录a(chǎn)生的線程。 observeOn(): 指定 Subscriber 所運(yùn)行在的線程?;蛘呓凶鍪录M(fèi)的線程。
比如說(shuō):
Observable.just(1, 2, 3, 4)
.subscribeOn(Schedulers.io()) // 指定 subscribe() 發(fā)生在 IO 線程
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回調(diào)發(fā)生在主線程
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer number) {
}
});```
上面這段代碼中,由于 subscribeOn(Schedulers.io()) 的指定,被創(chuàng)建的事件的內(nèi)容 1、2、3、4 將會(huì)在 IO 線程發(fā)出;而由于observeOn(AndroidScheculers.mainThread()) 的指定,因此 subscriber 數(shù)字的打印將發(fā)生在主線程 。事實(shí)上,這種在 subscribe() 之前寫上兩句 subscribeOn(Scheduler.io()) 和 observeOn(AndroidSchedulers.mainThread()) 的使用方式非常常見(jiàn),它適用于多數(shù)的 『后臺(tái)線程取數(shù)據(jù),主線程顯示』的程序策略。