此篇內容均是來自書籍《RxJava響應式編程》李衍順 著
一彤侍、什么是RxJava?
RxJava是一個非常著名的開源庫饥侵,是ReactiveX(Reactive Extensions)的一種Java實現(xiàn)颖侄。ReactiveX是一種響應式擴展框架萄凤,有很多種實現(xiàn),如RxAndroid, RxJS宋税,RxSwift摊崭,RxRuby,RxCpp,RxGo等。目前RxJava有1.x和2.x兩個主要分支弃甥,分別代表RxJava1和RxJava2爽室。RxJava1發(fā)布的時間比較早, 使用也更廣泛淆攻,所以先來了解下RxJava1阔墩。
RxJava可看作由Observable、Subscriber和Scheduler組成的瓶珊。Subscriber訂閱到Observable啸箫,Obervable會在默認或者指定的Scheduler上工作并產生數據流返回給Subscriber,Subscriber也會在默認或者指定的Scheduler上接收Observable發(fā)送過來的數據流伞芹。Scheduler是對線程的一種抽象忘苛,不同的Scheduler代表 了不同的線程。
1.1 Observable和Subscriber
Observable提供了subscribe方法唱较, 當有Subscriber通過subscribe方法訂閱到Observable時扎唾, Observable就可以向Subscriber發(fā)送數據流。響應式編程中的事件分為三類:普通事件 南缓,錯誤事件和結束事件胸遇,在Subscriber中有三個方法與這三件事一一對應,Observable會通過調用Subscriber的這三個方法來發(fā)送對應的事件汉形。
- onNext:當Observable要發(fā)送普通事件時纸镊,就會調用這個方法。這個方法可被調用0~N次概疆。
- onError: 當在Observable內部有異扯和或者錯誤產生時,就可以調用這個方法來向Subscriber發(fā)送錯誤事件岔冀。這個方法只能被調用一次凯旭。
- onComplete: 如果Observable已經發(fā)送完所有數據,并且沒有發(fā)生錯誤使套,這時就需要調用這個方法來向Subscriber發(fā)送結束事件罐呼。這個方法只能調用一次,而且和onError是互斥的關系童漩,也就是說調用了onError后就不能調用onComplete 反之亦然弄贿。在onError或者onComplete被調用之后春锋, Observable就失去了作用矫膨, 不能再調用onNext來發(fā)送數據了。
Subscriber還提供了unsubscribe方法, 當Subscriber訂閱到Observable之后侧馅, 可以隨時調用這個方法來終止對Observable的訂閱危尿。
二、在Android工程中引入RxJava
只需要在Gradle配置文件中加入對RxJava的依賴馁痴。但是Android開發(fā)中一般會添加對RxAndroid的依賴谊娇,而RxAndroid已經依賴于RxJava,且一般難以及時更新到最新版的RxJava罗晕,所以如果想使用RxAndroid和最新版本的RxJava济欢,則可以通過下面的配置來導入依賴。
api ('io.reactivex.rxjava2:rxandroid:2.1.0'){
exclude module:'rxjava2'
}
api 'io.reactivex.rxjava2:rxjava:2.2.1'
三小渊、RxJava中的操作符
3.1 創(chuàng)建Observable的操作符
3.1.1 range
range操作符創(chuàng)建的Observable將會發(fā)送一個范圍內的數據
Observable.range(0,4)
.subscribe(new Action1<Integer>(){
@Override
public void call(Integer integer) {
System.out.println(integer);
}
});
結果是:
0 1 2 3
3.1.2 defer和just
defer操作符法褥,只有當Subscriber來訂閱的時候才會創(chuàng)建一個新的Observable對象, 也就是說每次訂閱都會得到一個剛創(chuàng)建的最新的Observable對象酬屉,這可以確保Observable對象里的數據是最新的半等。
just操作符接收某個對象作為輸入,然后會創(chuàng)建一個發(fā)送該對象的Observable呐萨。這個對象可以是一個數字杀饵,一個字符串,數組谬擦,Iterate對象等切距。just是一種非常快捷的創(chuàng)建Observable對象的方法怯屉,在后面的例子中會大量使用蔚舀。
我們通過這兩個操作符創(chuàng)建兩個Observable,這兩個Observable都會將Android系統(tǒng)中的當前時間作為數據發(fā)送锨络。我們將這兩個Observable分別保存在變量deferObservable和justObservable中赌躺。
Observable<Long> deferObservable = getDefer();
Observable<Long> justObservable = getJust();
private Observable<Long> getJust() {
return Observable.just(System.currentTimeMillis());
}
private Observable<Long> getDefer() {
return Observable.defer(new Func0<Observable<Long>>() {
@Override
public Observable<Long> call() {
return getJust();
}
});
}
現(xiàn)在分別對這兩個Observable進行訂閱
private void Just_Defer(){
for(int i = 0; i<3;i++) {
deferObservable.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
System.out.println("defer: " + aLong);
}
});
justObservable.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
System.out.println("just: " + aLong);
}
});
}
}
輸出結果可以看到defer每次訂閱都會得到Observable發(fā)送的一個全新的當前時間, 而just創(chuàng)建的操作符即使訂閱多次也都會發(fā)出和首次訂閱一樣的數據羡儿。
defer: 1554532535942
just: 1554532535905
defer: 1554532535954
just: 1554532535905
defer: 1554532535954
just: 1554532535905
3.1.3 from
from操作符接收一個對象作為參數來創(chuàng)建Observable礼患,這個參數對象可以是Iterable、Callable掠归、Future和數組等缅叠。 from操作符創(chuàng)建的Observable將發(fā)送參數對象里的數據, 其創(chuàng)建方式類似于just操作符虏冻,但是just操作符創(chuàng)建的Observable會將整個參數對象作為數據一下子發(fā)送出去肤粱。 比如說參數對象是一個含有10個數字的數組,使用from創(chuàng)建的Observable就會發(fā)送10次厨相, 每次發(fā)送一個數字领曼,而使用just創(chuàng)建的Observable會一次就將整個數組發(fā)送出去鸥鹉。
首先創(chuàng)建一個數組和一個List, 分別存儲0~5的整數庶骄,然后使用from操作符分別以數組和List作為輸入參數創(chuàng)建兩個Observable對象毁渗。之后分別訂閱,會輸出什么結果呢单刁?
Integer[] arrays = {0,1,2,3,4,5};
List<Integer> list = new ArrayList<>();
private Observable<Integer> FromArray() {
return Observable.from(arrays);
}
private Observable<Integer> FromIterable() {
for(int i = 0;i <= 5; i++) {
list.add(i);
}
return Observable.from(list);
}
private void From(){
FromArray().subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("FromArray: " + integer);
}
});
FromIterable().subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("FromIterable: " + integer);
}
});
}
FromArray: 0
FromArray: 1
FromArray: 2
FromArray: 3
FromArray: 4
FromArray: 5
FromIterable: 0
FromIterable: 1
FromIterable: 2
FromIterable: 3
FromIterable: 4
FromIterable: 5
3.1.4 interval
interval所創(chuàng)建的Observable對象會從0開始灸异, 每隔固定的時間發(fā)送一個數字。需要注意的是羔飞, 這個對象時運行在computation Scheduler中的肺樟,所以在Android開發(fā)中 ,如果需要在UI中顯示結果逻淌, 則需要在主線程中訂閱儡嘶。
代碼通過interval操作符創(chuàng)建了一個Observable, 創(chuàng)建的Observable將會以1秒為間隔不斷地發(fā)送數據恍风,因為我們需要更新UI蹦狂,所以在主線程中進行訂閱。這里的AndroidSchedulers.mainThread()屬于RxAndroid庫朋贬, RxAndroid是Jake Wharton在Android平臺上開發(fā)的一個對RxJava的擴展凯楔。最后創(chuàng)建一個Subscriber對象對這個Observable對象進行訂閱, 就會每秒輸出一個從0開始遞增的數據锦募。
private void interval(){
Subscriber<Long> subscriber = new Subscriber<Long>() {
@Override
public void onCompleted() {
System.out.println("onCompleted");
}
@Override
public void onError(Throwable e) {
System.out.println("onError: " + e.getMessage());
}
@Override
public void onNext(Long aLong) {
System.out.println("onNext:" + aLong);
}
};
Observable.interval(0,10, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
}
最后結果是摆屯,原因不知道
onError: null
最后,由于interval操作符創(chuàng)建的Observable對象會不停地發(fā)送數據糠亩,所以當我們不再需要它的數據時要調用unSubscribe方法進行反訂閱虐骑,反訂閱后Observable將會停止發(fā)送數據
subscriber.unsubscribe();
3.1.5 repeat和timer
repeat操作符可以讓Observable對象發(fā)送的數據重復發(fā)送N次, 我們可以指定其發(fā)送的次數赎线。timer操作符創(chuàng)建的Observable會在指定時間后發(fā)送一個數字0廷没, 注意其默認也是運行在computation scheduler 上。
下面我們來創(chuàng)建一個發(fā)送整數1垂寥,2颠黎,3的源Observable, 并使用repeat操作符在源Observable的基礎上創(chuàng)建一個新的Observable滞项,使其重復發(fā)送數據3次狭归。另外使用timer創(chuàng)建一個會在1秒后發(fā)送數據的Observable。
private void Repeat_Timer() {
Observable.just(1,2,3).repeat(3)
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("repeat: " + integer);
}
});
Observable.timer(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
System.out.println("timer: " + aLong);
}
});
}
結果呢文判,后面的這個報空指針異常过椎,還沒找到原因;正常timer操作符創(chuàng)建的Observable在訂閱1秒后發(fā)送一個數據0.
repeat: 1
repeat: 2
repeat: 3
repeat: 1
repeat: 2
repeat: 3
repeat: 1
repeat: 2
repeat: 3
另外還有幾個非常簡單的創(chuàng)建操作符戏仓,如naver疚宇、empty竞惋、throw等,請移步查看官方文檔灰嫉。