RxJava是ReactiveX的一種Java實(shí)現(xiàn)。ReactiveX是Reactive Extensions的縮寫,一般簡寫為Rx。開發(fā)者可以用Observables表示異步數(shù)據(jù)流,用LINQ操作符查詢異步數(shù)據(jù)流,用Schedulers參數(shù)化異步數(shù)據(jù)流的并發(fā)處理,Rx可以這樣定義:Rx = Observables + LINQ + Schedulers。
- 或許你會問:我為什么要選擇RxJava ?
一般我們在開發(fā)的時候,只要說到異步操作,就會想到Android的AsyncTask和Handler。但是隨著請求的數(shù)量越來越多,
代碼邏輯將會變得越來越復(fù)雜,而RxJava卻仍舊能保持清晰的邏輯。RxJava的原理就是創(chuàng)建一個Observable對象來干活,
然后使用各種操作符建立起來的鏈?zhǔn)讲僮鳎腿缤魉€一樣,把你想要處理的數(shù)據(jù)一步一步加工成你想要的成品,
然后發(fā)射給Subscriber處理。
- RxJava與觀察者模式
RxJava的異步操作是通過擴(kuò)展的觀察者模式來實(shí)現(xiàn)的。RxJava有4個角色:Observable、Observer、Subscriber和Suject。
Observable和Observer通過subscribe方法實(shí)現(xiàn)訂閱關(guān)系,Observable就可以在需要的時候通知Observer。
- RxJava的實(shí)現(xiàn)
在使用RxJava前請先在AndroidStudio配置gradle:(此處以RxJava為例,不使用RxJava2)
dependencies {
...
compile 'io.reactivex:rxjava:1.2.0'
compile 'io.reactivex:rxandroid:1.2.1'
}
看到這里可能會問:我使用的是RxJava,為什么還要引入RxAndroid ?
RxAndroid是RxJava在Android平臺的擴(kuò)展。包含了一些能夠簡化Android開發(fā)的工具,比如特殊的調(diào)度器。
- RxJava的使用
RxJava的使用可以分為3個步驟:創(chuàng)建Observable(被觀察者)、創(chuàng)建Observer(觀察者)、Subscribe(訂閱)。
創(chuàng)建Observable(被觀察者)
Observable它決定什么時候觸發(fā)事件以及觸發(fā)怎樣的事件。RxJava使用 create 方法來創(chuàng)建一個Observable,并未它定義時間觸發(fā)規(guī)則。例如:
// 創(chuàng)建Observable(被觀察者)
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("張三");
subscriber.onNext("李四");
subscriber.onCompleted();
}
});
通過調(diào)用Subscriber的方法,不斷的將事件添加到任務(wù)隊列中。
創(chuàng)建Observer(觀察者)
Observer 它決定事件觸發(fā)的時候?qū)⒂性趺礃拥男袨椤?/p>
// 創(chuàng)建Observer(觀察者)
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onStart() {
Log.e(TAG, "onStart");
}
@Override
public void onCompleted() {
Log.e(TAG, "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError");
}
@Override
public void onNext(String s) {
Log.e(TAG, "onNext" + s);
}
};
其中,onCompleted、onError和onNext是必須要實(shí)現(xiàn)的方法。其具體含義如下:
onCompleted:事件隊列完結(jié)。RxJava不僅把每個事件單獨(dú)處理,其還會把它們看作一個隊列。當(dāng)不會有新的 onNext 發(fā)出時,需要觸發(fā) onComplete() 方法作為完成標(biāo)志。
onError:事件隊列異常。在事件處理過程中出現(xiàn)異常時,onError() 方法會被觸發(fā),同時隊列自動終止,不允許再有事件發(fā)出。
onNext():普通的事件。將要處理的事件添加到事件隊列中。
onStart():它會在事件還未發(fā)送之前被調(diào)用,可以用于做一些準(zhǔn)備工作。例如數(shù)據(jù)的清零或重置。這是一個可選方法,默認(rèn)情況下它的實(shí)現(xiàn)為空。
當(dāng)然,如果要實(shí)現(xiàn)簡單的功能,也可以用到Observer來創(chuàng)建觀察者。Observer是一個接口,而上面用到的Subscriber是在Observer的基礎(chǔ)上進(jìn)行的擴(kuò)展。在后文的Subscribe訂閱過程中Observer也會被轉(zhuǎn)換為Subscriber來使用。如果用Observer創(chuàng)建觀察者對象,如下:
Observer<String> observer = new Observer<String>() {
@Override
public void onCompleted() {
Log.e(TAG, "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError");
}
@Override
public void onNext(String s) {
Log.e(TAG, "onNext" + s);
}
};
Subscribe(訂閱)
observable.subscribe(subscriber);
運(yùn)行代碼可查看Log:
E/RxJavaActivity: onStart
E/RxJavaActivity: onNext張三
E/RxJavaActivity: onNext李四
E/RxJavaActivity: onCompleted
RxJava操作符
RxJava操作符類型可以分為:創(chuàng)建操作符、變換操作符、過濾操作符、組合操作符、錯誤處理操作符、輔助操作符、條件和布爾操作符、算術(shù)和聚合操作符及連續(xù)操作符等,而這些操作符類型下又有很多操作符,每個操作符可能還有很多變體。此處,簡單的介紹一些創(chuàng)建操作符、變換操作符、過濾操作符、輔助操作符、錯誤處理操作符。
創(chuàng)建操作符
- Interval
創(chuàng)建一個按固定時間間隔發(fā)射整數(shù)序列的Observable,相當(dāng)于定時器,如下:
Observable.interval(3, TimeUnit.SECONDS)
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
Log.e(TAG, "interval:" + aLong.intValue());
}
});
上面的代碼每個3s就會調(diào)用call方法并打印Log。
- Range
創(chuàng)建發(fā)射指定范圍的整數(shù)序列的Observable,可以拿來代替for循環(huán),發(fā)射一個范圍內(nèi)的有序整數(shù)序列。第一個參數(shù)是起始值,并不小于0;第二個參數(shù)為整數(shù)序列的個數(shù)。
Observable.range(0, 5)
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e(TAG, "range:" + integer.intValue());
}
});
運(yùn)行代碼可查看Log:
E/RxJavaActivity: range:0
E/RxJavaActivity: range:1
E/RxJavaActivity: range:2
E/RxJavaActivity: range:3
E/RxJavaActivity: range:4
- Repeat
創(chuàng)建一個N次重復(fù)發(fā)射特定數(shù)據(jù)的Observable,如下:
Observable.range(0, 3)
.repeat(2)
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e(TAG, "repeat:" + integer.intValue());
}
});
運(yùn)行代碼可查看Log:
E/RxJavaActivity: repeat:0
E/RxJavaActivity: repeat:1
E/RxJavaActivity: repeat:2
E/RxJavaActivity: repeat:0
E/RxJavaActivity: repeat:1
E/RxJavaActivity: repeat:2
變換操作符
- Map
map操作符通過指定一個Func對象,將Observable轉(zhuǎn)換為一個新的Observable對象并發(fā)射,觀察者將收到最新的Observable處理。例如:
final String host = "https://github.com/";
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("JiaYang627");
}
}).map(new Func1<String, String>() {
@Override
public String call(String s) {
return host + s;
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e(TAG, "map:" + s);
}
});
運(yùn)行代碼查看Log:
E/RxJavaActivity: map:https://github.com/JiaYang627
過濾操作符
- Filter
Filter操作符是對源Observable產(chǎn)生的結(jié)果自定義規(guī)則進(jìn)行過濾,只有滿足條件的結(jié)果才會交給訂閱者。例如:
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onNext(1);
subscriber.onNext(2);
subscriber.onNext(3);
subscriber.onNext(4);
}
}).filter(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return integer > 2;
}
}).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e(TAG, "filter:" + integer);
}
});
運(yùn)行代碼查看Log:
E/RxJavaActivity: filter:3
E/RxJavaActivity: filter:4
輔助操作符
- Do
Do系列操作符是為原始Observable的生命周期事件注冊一個回調(diào),當(dāng)Observable的某個事件發(fā)生時就會調(diào)用這些回調(diào)。RxJava中有很多Do系列操作符,如下:
- doOnEach:為Observable注冊這樣一個回調(diào):當(dāng)Observable每當(dāng)發(fā)射一項數(shù)據(jù)時就會調(diào)用它一次,包括onNext、onError和onCompleted。
- doOnNext:只有執(zhí)行onNext的時候會被調(diào)用。
- doOnSubscribe:當(dāng)觀察者訂閱Observable時就會被調(diào)用。
- doOnUnsubscribe:當(dāng)觀察者取消訂閱Observable時就會被調(diào)用;Observable通過onError或者onCompleted結(jié)束時,會取消訂閱所有的Subscriber。
- doOnCompleted:當(dāng)Observable正常終止調(diào)用onCompleted時會被調(diào)用。
- doOnError:當(dāng)Observable異常終止調(diào)用onError時會被調(diào)用。
- doOnTerminate:當(dāng)Observable終止(無論是正常終止還是異常終止)之前會被調(diào)用。
- finallyDo:當(dāng)Observable終止(無論是正常終止還是異常終止)之后會被調(diào)用。
此處以doOnNext為例,如下:
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onNext(1);
subscriber.onNext(2);
}
}).doOnNext(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e(TAG, "doOnNext:" + integer);
}
}).subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
Log.e(TAG, "subscribe_onNext:" + integer);
}
});
運(yùn)行代碼查看Log:
E/RxJavaActivity: doOnNext:1
E/RxJavaActivity: subscribe_onNext:1
E/RxJavaActivity: doOnNext:2
E/RxJavaActivity: subscribe_onNext:2
- SubscribeOn、ObserverOn
SubscribeOn操作符用于指定Obserable自身在哪個線程上運(yùn)行。如果Observable需要執(zhí)行耗時操作,一般可以讓其在新開的一個子線程上運(yùn)行。ObserverOn用來指定Observer所運(yùn)行的線程,也就是發(fā)射出的數(shù)據(jù)在哪個線程上使用。一般情況下會指定砸死主線程中運(yùn)行,這樣就可以修改UI。如下:
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
Log.e(TAG, "Observable:" + Thread.currentThread().getName());
subscriber.onNext(1);
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e(TAG, "Observer:" + Thread.currentThread().getName());
}
});
運(yùn)行代碼查看Log:
E/RxJavaActivity: Observable:RxIoScheduler-2
E/RxJavaActivity: Observer:main
其中,AndroidSchedulers是RxAndroid庫中提供的Scheduler。
錯誤處理操作符
- Retry
Retry操作符不會將原始Observable的onError通知傳遞給觀察者,它會訂閱這個Observable再給它一次機(jī)會無錯誤地完成其數(shù)據(jù)序列。Retry總是傳遞onNext通知給觀察者,由于重新訂閱,這可能會造成數(shù)據(jù)項重復(fù)。RxJava中的實(shí)現(xiàn)為Retry和RetryWhen。此處以Retry為例說明。
它指定最多重新訂閱的次數(shù),如果次數(shù)超了,它不會嘗試再次訂閱,而會把最新的一個onError通知傳遞給自己的觀察者。如下:
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for (int i =0 ; i < 5 ; i ++) {
if (i == 1) {
subscriber.onError(new Throwable("Throwable"));
} else {
subscriber.onNext(i);
}
}
}
}).retry(2)
.subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.e(TAG, "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError:" + e.getMessage());
}
@Override
public void onNext(Integer integer) {
Log.e(TAG, "onNext:" + integer);
}
});
如上所示,Observable中走了一個for循環(huán),當(dāng)i為0時走onNext,當(dāng)i為1時讓走onError,然后,此時會重新訂閱,再次走for循環(huán),此為第一次重新訂閱。在第二次重新訂閱的時候,走到onError后不會再次重新訂閱,運(yùn)行代碼查看Log:
E/RxJavaActivity: onNext:0
E/RxJavaActivity: onNext:0
E/RxJavaActivity: onNext:0
E/RxJavaActivity: onError:Throwable
RxJava結(jié)合Retrofit訪問網(wǎng)絡(luò)
此處使用自己寫的MVP框架Demo為例,使用的是RxJava2、Retrofit2。
- 首先配置build.gradle:
dependencies {
...
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
compile 'org.ligboy.retrofit2:converter-fastjson-android:2.1.0'
compile 'com.squareup.retrofit2:converter-scalars:2.1.0'
compile 'com.alibaba:fastjson:1.2.33'
}
以上為配置依賴,Demo中使用FastJson數(shù)據(jù)解析。
配置Retorfit:
private Retrofit creatRetrofit(Retrofit.Builder builder, String baseUrl, OkHttpClient client){
builder.client(client)
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(FastJsonConverterFactory.create());
return builder.build();
}
- 注意:由于MVP框架使用的是Dagger2 + RxJava2 + Retrofit2 + OkHttp3 + FastJson。此處只說配置Retrofit。
上面配置Retrofit的時候,添加 addCallAdapterFactory方法,這樣此前Retrofit定義的接口返回的就不是Call了,而是Observalbe,這樣就能用RxJava提供的方法來對請求網(wǎng)絡(luò)的回調(diào)進(jìn)行處理。添加的addConverterFactory方法支持對返回結(jié)構(gòu)的支持類型,此處支持的為FastJson 和String類型。
最后,給出MVP框架的地址,此項目框架采用 OkHttp3 + RxJava2 + Retrofit2 + Dagger2 + FastJson 為主體的 mvp框架。里面有詳細(xì)的Retrofit配置,已經(jīng)RxJava請求聯(lián)網(wǎng)時線程轉(zhuǎn)換。
Demo:
MVPFramework