Rxjava(https://gank.io/post/560e15be2dca930e00da1083#toc_4)
(1).Rxjava是一個(gè)用于處理異步和基于事件編程的Java庫(kù).
(2).Rxjava原理就是類似于觀察者模式
觀察者模式面向的需求是:A 對(duì)象(觀察者)對(duì) B 對(duì)象(被觀察者)的某種變化高度敏感结榄,需要在 B 變化的一瞬間做出反應(yīng)。舉個(gè)例子,新聞里喜聞樂見的警察抓小偷,警察需要在小偷伸手作案的時(shí)候?qū)嵤┳ゲ丁T谶@個(gè)例子里叮雳,警察是觀察者,小偷是被觀察者,警察需要時(shí)刻盯著小偷的一舉一動(dòng)段磨,才能保證不會(huì)漏過任何瞬間。程序的觀察者模式和這種真正的『觀察』略有不同耗绿,觀察者不需要時(shí)刻盯著被觀察者(例如 A 不需要每過 2ms 就檢查一次 B 的狀態(tài))苹支,而是采用注冊(cè)(Register)或者稱為訂閱(Subscribe)的方式,告訴被觀察者:我需要你的某某狀態(tài)误阻,你要在它變化的時(shí)候通知我债蜜。 Android 開發(fā)中一個(gè)比較典型的例子是點(diǎn)擊監(jiān)聽器 OnClickListener 。對(duì)設(shè)置 OnClickListener 來說究反, View 是被觀察者寻定, OnClickListener 是觀察者,二者通過 setOnClickListener() 方法達(dá)成訂閱關(guān)系精耐。訂閱之后用戶點(diǎn)擊按鈕的瞬間狼速,Android Framework 就會(huì)將點(diǎn)擊事件發(fā)送給已經(jīng)注冊(cè)的 OnClickListener 。采取這樣被動(dòng)的觀察方式卦停,既省去了反復(fù)檢索狀態(tài)的資源消耗向胡,也能夠得到最高的反饋速度。當(dāng)然惊完,這也得益于我們可以隨意定制自己程序中的觀察者和被觀察者僵芹,而警察叔叔明顯無法要求小偷『你在作案的時(shí)候務(wù)必通知我』
RxJava 有四個(gè)基本概念:Observable (可觀察者,即被觀察者)小槐、 Observer (觀察者)拇派、 subscribe (訂閱)、事件凿跳。Observable 和 Observer 通過 subscribe() 方法實(shí)現(xiàn)訂閱關(guān)系攀痊,從而 Observable 可以在需要的時(shí)候發(fā)出事件來通知 Observer。
//.create創(chuàng)建了一個(gè)Observable<String> 的可發(fā)射事件.
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) {
e.onNext("1"); //可以多次調(diào)用
e.onNext("1"); //可以多次調(diào)用
e.onComplete();
// e.onError(new Exception());
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
在 RxJava 的 subscribe 過程中拄显,Observer 也總是會(huì)先被轉(zhuǎn)換成一個(gè) Subscriber 再使用苟径。所以如果你只想使用基本功能,選擇 Observer 和 Subscriber 是完全一樣的躬审。它們的區(qū)別對(duì)于使用者來說主要有兩點(diǎn)棘街。
A:onStart():這是 Subscriber 增加的方法蟆盐。
B: unsubscribe(): 這是 Subscriber 所實(shí)現(xiàn)的另一個(gè)接口 Subscription 的方法,用于取消訂閱,
一般在這個(gè)方法調(diào)用前遭殉,可以使用 isUnsubscribed() 先判斷一下狀態(tài)石挂。 unsubscribe() 這個(gè)方法很重要,因?yàn)樵?subscribe() 之后险污, Observable 會(huì)持有 Subscriber 的引用痹愚,這個(gè)引用如果不能及時(shí)被釋放,將有內(nèi)存泄露的風(fēng)險(xiǎn)蛔糯。所以最好保持一個(gè)原則:要在不再使用的時(shí)候盡快在合適的地方(例如 onPause() onStop() 等方法中)調(diào)用 unsubscribe() 來解除引用關(guān)系拯腮,以避免內(nèi)存泄露的發(fā)生。
(3).操作符
(3-1)just操作符創(chuàng)建Observable被觀察者對(duì)象
Observable.just(1,2,3,4,5).subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.i(TAG,"onCompleted:");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
Log.i(TAG,"onNext:"+integer);//執(zhí)行5次
}
});
(3-2)map蚁飒,floatmap,filter ,take ,takelast,distinct,skip變換操作符
map操作符----將原Observable發(fā)射出來的數(shù)據(jù)轉(zhuǎn)換為另外一種類型的數(shù)據(jù)
Observable.just("666").map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
return Integer.parseInt(s);
}
}).subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
floatmap操作符---作用類似于map又比map強(qiáng)大动壤,map是單純的數(shù)據(jù)類型的轉(zhuǎn)換,而flapMap可以將原數(shù)轉(zhuǎn)換成新的Observables淮逻,再將這些Observables的數(shù)據(jù)順序緩存到一個(gè)新的隊(duì)列中琼懊,在統(tǒng)一發(fā)射出來
List<AccountInfoBean> infoBeans=new ArrayList<>();
infoBeans.add(new AccountInfoBean());
infoBeans.add(new AccountInfoBean());
infoBeans.add(new AccountInfoBean());
Observable.just(infoBeans).flatMap(new Function<List<AccountInfoBean>, ObservableSource<AccountInfoBean>>() {
@Override
public ObservableSource<AccountInfoBean> apply(List<AccountInfoBean> beanList) throws Exception {
//把beanList中的每個(gè)對(duì)象轉(zhuǎn)換成Observable<AccountInfoBean>
return Observable.fromIterable(beanList);
}
}).subscribe(new Consumer<AccountInfoBean>() {
@Override
public void accept(AccountInfoBean accountInfoBean) throws Exception {
System.out.println("xxx");//infoBeans中有3個(gè)元素,會(huì)執(zhí)行3次
}
});
filter操作符----對(duì)發(fā)射的數(shù)據(jù)做一個(gè)限制爬早,只有滿足條件的數(shù)據(jù)才會(huì)被發(fā)射
//對(duì)發(fā)射的數(shù)據(jù)做一個(gè)限制哼丈,只有滿足條件的數(shù)據(jù)才會(huì)被發(fā)射
Observable.just("hello","Rxjava","Nice to meet you").filter(new Function<String, Boolean>() {
@Override
public Boolean apply(String s) {
return s.length()>5;
}
}).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onNext(String s) {
Log.i("TAG","filter過濾后的數(shù)據(jù):"+s.toString());
}
});
distinct操作符----過濾掉重復(fù)項(xiàng)
Observable.just("hello","hello","hello","Rxjava","Rxjava","Nice to meet you").filter(new Function<String, Boolean>() {
@Override
public Boolean apply(String s) {
return s.length()>5;
}
}).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onNext(String s) {
Log.i("TAG","distinct去除重復(fù)之后的數(shù)據(jù):"+s.toString());
}
});
Skip操作符----發(fā)射數(shù)據(jù)時(shí)忽略前N項(xiàng)數(shù)據(jù)(skpiLast忽略后N項(xiàng)數(shù)據(jù))
Observable.just("hello","Rxjava","Nice to meet you").skip(2).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onNext(String s) {
Log.i("TAG","Skip之后的數(shù)據(jù):"+s.toString());
}
});
take操作符----只發(fā)射前N項(xiàng)的數(shù)據(jù)(takeLast與take想反,只取最后N項(xiàng)數(shù)據(jù))
Observable.just("hello","Rxjava","Nice to meet you").take(2).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onNext(String s) {
Log.i("TAG","Take之后的數(shù)據(jù):"+s.toString());
}
});
另外還有一些其他的操作符 range,Interval筛严,empty,error等(http://www.reibang.com/p/eceb6b31d8cb)
(3-3).線程調(diào)度Scheduler
Observable.just(1, 2, 3, 4)
.subscribeOn(Schedulers.io()) // 指定 subscribe() 發(fā)生在 IO 線程
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回調(diào)發(fā)生在主線程
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
- Rxjava解決回調(diào)地獄問題(OkHttp會(huì)導(dǎo)致回調(diào)地獄削祈,無法切換線程)
api.requestFirstData()
.flatMap(data1 -> api.requestSecondData(data1.getId()))
.flatMap(data2 -> api.requestThirdData(data2.getToken()))
.subscribe(
data3 -> {
// 處理最終數(shù)據(jù)
},
throwable -> {
// 處理錯(cuò)誤,這里不管是哪個(gè)環(huán)節(jié)出錯(cuò)脑漫,都會(huì)走到這里
}
);