什麼是Rx
Rx是一個函數庫,讓開發者可以利用可觀察序列和LINQ風格查詢操作符來編寫異步和基於事件的程序。簡單來講Rx就是一種響應式編程,來創建基於事件的異步程序
RxJava 到底是什麼
RxJava 在 GitHub 主頁上的自我介紹是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"也就是官方定義:一個在 Java VM 上使用可觀測的序列來組成異步的、基於事件的程序的庫。
然而,對於初學者來說,這太難看懂了。因爲它是一個『總結』,而初學者更需要一個『引言』。
其實, RxJava 的本質可以壓縮爲異步這一個詞。說到根上,它就是一個實現異步操作的庫,而別的定語都是基於這之上的。
然而,對於初學者來說,這太難看懂了。因爲它是一個『總結』,而初學者更需要一個『引言』。
其實, RxJava 的本質可以壓縮爲異步這一個詞。說到根上,它就是一個實現異步操作的庫,而別的定語都是基於這之上的。
RxJava 的異步實現,是通過一種擴展的觀察者模式來實現的。
觀察者模式
- 普通的觀察者模式:
其中這個Button就是被觀察者(Observable),OnClickListener就是觀察者(Observer),兩者通過setOnClickListener達成訂閱(Subscribe)關係,之後當Button產生OnClick事件的時候,會直接發送給OnClickListener,它做出相應的響應處理。
- RxJava的觀察者模式呢,跟這個差不多,但是也有幾點差別:
Observer與Observable是通過 subscribe() 來達成訂閱關係。
RxJava中事件回調有三種:onNext() 、 onCompleted() 、 onError() 。
如果一個Observerble沒有任何的Observer,那麼這個Observable是不會發出任何事件的。
RxJava中事件回調有三種:onNext() 、 onCompleted() 、 onError() 。
如果一個Observerble沒有任何的Observer,那麼這個Observable是不會發出任何事件的。
關於RxJava的回調事件:
- onNext():基本事件。
- onCompleted(): 事件隊列完結。RxJava 不僅把每個事件單獨處理,還會把它們看做一個隊列。RxJava 規定,當不會再有新的 onNext() 發出時,需要觸發 onCompleted() 方法作爲標誌。
- onError(): 事件隊列異常。在事件處理過程中出異常時,onError() 會被觸發,同時隊列自動終止,不允許再有事件發出。
RxJava 好在哪
換句話說,『同樣是做異步,爲什麼人們用它,而不用現成的 AsyncTask / Handler / XXX / ... ?』
異步操作很關鍵的一點是程序的簡潔性,因爲在調度過程比較複雜的情況下,異步代碼經常會既難寫也難被讀懂。 Android 創造的 AsyncTask 和Handler ,其實都是爲了讓異步代碼更加簡潔。RxJava 的優勢也是簡潔,但它的簡潔的與衆不同之處在於,隨着程序邏輯變得越來越複雜,它依然能夠保持簡潔。
異步操作很關鍵的一點是程序的簡潔性,因爲在調度過程比較複雜的情況下,異步代碼經常會既難寫也難被讀懂。 Android 創造的 AsyncTask 和Handler ,其實都是爲了讓異步代碼更加簡潔。RxJava 的優勢也是簡潔,但它的簡潔的與衆不同之處在於,隨着程序邏輯變得越來越複雜,它依然能夠保持簡潔。
如何實現RxJava
- 創建Observer
//1.創建觀察者對象
Observer<String> observer=new Observer<String>() {
@Override
public void onCompleted() {
Log.e("kaka","onComlieted");
}
@Override
public void onError(Throwable e) {
Log.e("kaka","onError");
}
@Override
public void onNext(String s) {
Log.e("kaka","onNext");
}
};
- 創建Observable
//2.創建被觀察者對象
Observable<String> observable=Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("hi");
subscriber.onNext("nihao");
subscriber.onNext("kaka");
subscriber.onCompleted();
}
});
- 現在就需要用 subscribe() 方法來將它們連接起來,形成一種訂閱關係:
observable.subscribe(observer);
這裏其實確實有點奇怪,爲什麼是Observable(被觀察者)訂閱了Observer(觀察者)呢?其實我們想一想之前Button的點擊事件:
Button.setOnClickListener(new View.OnClickListener())
Button是被觀察者,OnClickListener是觀察者,setOnClickListener是訂閱。我們驚訝地發現,也是被觀察者訂閱了觀察者,所以應該是一種流式API的設計吧,也沒啥影響。
線程控制——Scheduler
在RxJava中,Scheduler相當於線程控制器,可以通過它來指定每一段代碼運行的線程。
RxJava已經內置了幾個Scheduler
Schedulers.immediate(): 直接在當前線程運行,相當於不指定線程。這是默認的Scheduler。
Schedulers.newThread(): 總是啓用新線程,並在新線程執行操作。
Schedulers.io(): I/O 操作(讀寫文件、讀寫數據庫、網絡信息交互等)所使用的Scheduler。行爲模式和newThread()差不多,區別在於io()的內部實現是是用一個無數量上限的線程池,可以重用空閒的線程,因此多數情況下io()比newThread()更有效率。不要把計算工作放在io()中,可以避免創建不必要的線程。
Schedulers.computation(): 計算所使用的Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作,例如圖形的計算。這個Scheduler使用的固定的線程池,大小爲 CPU 核數。不要把 I/O 操作放在computation()中,否則 I/O 操作的等待時間會浪費 CPU。
AndroidSchedulers.mainThread(),Android專用線程,指定操作在主線程運行。(需要導入RxAndroid依賴)
那我們如何切換線程呢?RxJava中提供了兩個方法:subscribeOn() 和 observeOn() ,兩者的不同點在於:
subscribeOn(): 指定subscribe()訂閱所發生的線程,即 call() 執行的線程。或者叫做事件產生的線程。
observeOn(): 指定Observer所運行在的線程,即onNext()執行的線程。或者叫做事件消費的線程。
RxJava已經內置了幾個Scheduler
Schedulers.immediate(): 直接在當前線程運行,相當於不指定線程。這是默認的Scheduler。
Schedulers.newThread(): 總是啓用新線程,並在新線程執行操作。
Schedulers.io(): I/O 操作(讀寫文件、讀寫數據庫、網絡信息交互等)所使用的Scheduler。行爲模式和newThread()差不多,區別在於io()的內部實現是是用一個無數量上限的線程池,可以重用空閒的線程,因此多數情況下io()比newThread()更有效率。不要把計算工作放在io()中,可以避免創建不必要的線程。
Schedulers.computation(): 計算所使用的Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作,例如圖形的計算。這個Scheduler使用的固定的線程池,大小爲 CPU 核數。不要把 I/O 操作放在computation()中,否則 I/O 操作的等待時間會浪費 CPU。
AndroidSchedulers.mainThread(),Android專用線程,指定操作在主線程運行。(需要導入RxAndroid依賴)
那我們如何切換線程呢?RxJava中提供了兩個方法:subscribeOn() 和 observeOn() ,兩者的不同點在於:
subscribeOn(): 指定subscribe()訂閱所發生的線程,即 call() 執行的線程。或者叫做事件產生的線程。
observeOn(): 指定Observer所運行在的線程,即onNext()執行的線程。或者叫做事件消費的線程。
Observable.just("hi","nihao","woshi")
.subscribeOn(Schedulers.io())//被創建的事件內容"hi","nihao","woshi"將會在io線程發出
.observeOn(AndroidSchedulers.mainThread())//字符串的打印將發生在主線程
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("kaka",s);
}
});
一個基於RxJava的Demo
/**
* 點擊按鈕,imageview顯示圖片
*
* @param view
*/
public void downloadImg(View view) {
Observable.create(new Observable.OnSubscribe<Bitmap>() {
@Override
public void call(Subscriber<? super Bitmap> subscriber) {
subscriber.onNext(GetBitmapForUrl.getBitmap(url));//通過URL得到圖片的bitmap對象
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Bitmap>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
}
});
}
運行結果:
幾篇關於RxJava的文章:
Rx系列之RxJava操作符:http://www.jianshu.com/p/30e13d874a61
Rx系列之Rxjava操作符進階-使用場景:http://www.jianshu.com/p/79cb4e1c9771