實踐才是真道理!實踐才是真道理!實踐才是真道理!
Rxjava 是什么?
異步,還是異步,還是異步!重復三遍幫助記憶,哈哈哈。
Rxjava 優點 ?
簡潔,還是簡潔,還是簡潔!
理解
handler、asyncTask是android提供的異步操作,我們通常配合回調來實現,而Rxjava是通過一個擴展的觀察者模式來現實的,支持鏈式調用,不需要回調來實現,從而一目了然,并且更好的維護。
簡潔的與眾不同之處:隨著程序邏輯變得越來越復雜,它依然能夠保持簡潔。
Rxjava 如何實現異步
RxJava 的異步實現,是通過一種擴展的觀察者模式來實現的。
觀察者模式
RxJava 有四個基本概念:
1: Observable (被觀察者)
2: Observer (觀察者)
3: subscribe (訂閱)
4: 事件
Observable 和 Observer 通過 subscribe() 方法實現訂閱關系,從而 Observable 可以在需要的時候發出事件來通知 Observer。
就是:被觀察者訂閱觀察者,被觀察者發生事件通知觀察者!(有點繞理解理解,哈哈。)
基本實現
1: 觀察者Observer
Observer是個抽象類,Subscriber是觀察者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!");
}
};
Subscriber<String> subscriber = new Subscriber<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!");
}
};
2: 被觀察者
創建被觀察者Observable有幾種方式,如下:
1:使用 create() 方法來創建
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello");
subscriber.onNext("Hi");
subscriber.onNext("Aloha");
subscriber.onCompleted();
}
});
可以看到,這里傳入了一個 OnSubscribe 對象作為參數。OnSubscribe 會被存儲在返回的 Observable 對象中,它的作用相當于一個計劃表,當 Observable 被訂閱的時候,OnSubscribe 的 call() 方法會自動被調用,事件序列就會依照設定依次觸發(對于上面的代碼,就是觀察者Subscriber 將會被調用三次 onNext() 和一次 onCompleted())。這樣,由被觀察者調用了觀察者的回調方法,就實現了由被觀察者向觀察者的事件傳遞,即觀察者模式。
just(T...)創建被觀察者Observable: 將傳入的參數依次發送出來。
Observable observable = Observable.just("Hello", "Hi", "Aloha");
// 將會依次調用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();
from(T[]) / from(Iterable<? extends T>) : 將傳入的數組或 Iterable 拆分成具體對象后,依次發送出來。
String[] words = {"Hello", "Hi", "Aloha"};
Observable observable = Observable.from(words);
// 將會依次調用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();
3:訂閱Subscribe
observable.subscribe(observer);
// 或者:
observable.subscribe(subscriber);
那么一個完整的是這樣的:
//創建Observable
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for (int i = 0; i < 5; i++) {
subscriber.onNext(i);
}
subscriber.onCompleted();
}
}).subscribe(new Observer<Integer>() {//訂閱方法,調用創建的Observer
@Override
public void onCompleted() {
System.out.println("onCompleted");
}
@Override
public void onError(Throwable e) {
System.out.println("onError");
}
@Override
public void onNext(Integer item) {
System.out.println("Item is " + item);
}
});
異步
上面簡單的調用,木有實現異步哦,而Rxjava最重要的不是異步嗎!RxJava 遵循的是線程不變的原則,即:在哪個線程調用 subscribe(),就在哪個線程生產事件;在哪個線程生產事件,就在哪個線程消費事件。如果需要切換線程,就需要用到 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 主線程運行。
那么如何調用呢?代碼如下:
Observable.just(1, 2, 3, 4)
.subscribeOn(Schedulers.io()) // 指定 subscribe() 發生在 IO 線程
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回調發生在主線程
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer number) {
Log.d(tag, "number:" + number);
}
});
其中的兩個方法subscribeOn() 和 observeOn() 兩個方法來對線程進行控制了。
subscribeOn(): 指定 subscribe() 所發生的線程,即 Observable.OnSubscribe 被激活時所處的線程。或者叫做事件產生的線程。
observeOn(): 指定 Subscriber 所運行在的線程。或者叫做事件消費的線程。
subscribeOn() 方法 --- 被觀察者事件的線程
observeOn() 方法 --- 觀察者事件的線程
上面這段代碼中,由于 subscribeOn(Schedulers.io()) 的指定,被創建的事件的內容 1、2、3、4 將會在 IO 線程發出;而由于 observeOn(AndroidScheculers.mainThread()) 的指定,因此 subscriber 數字的打印將發生在主線程 。事實上,這種在 subscribe() 之前寫上兩句 subscribeOn(Scheduler.io()) 和 observeOn(AndroidSchedulers.mainThread()) 的使用方式非常常見,它適用于多數的 『后臺線程取數據,主線程顯示』的程序策略。
好了,RxJava基本了解就是這些。下面這樣學習相關的API和操作符,并以實踐為基礎。