前言
終于到了講RxJava這一期注服,RxJava是筆者個(gè)人非常喜歡的一個(gè)開源庫(kù),它很好的將鏈?zhǔn)骄幊田L(fēng)格和異步結(jié)合在一起橱健。RxJava其實(shí)已經(jīng)推出很久了旬盯,可以說(shuō)是已經(jīng)很火了台妆,但是目前仍然還有相當(dāng)一部分Android開發(fā)者沒(méi)有使用過(guò),甚至說(shuō)是想用胖翰,卻不知道怎么用接剩,或者不知道自己的項(xiàng)目哪里可以用到,本著讓廣大開發(fā)者理解并且上手項(xiàng)目萨咳,從放棄到入門懊缺,故推出這邊文章。
注:本文所有的具體代碼實(shí)現(xiàn)都在文章最后的github鏈接上
學(xué)習(xí)RxJava2.0之前需不需要學(xué)習(xí)RxJava1.0
首先培他,RxJava1.0和RxJava2.0的核心思想都是觀察者模式鹃两,只不過(guò)RxJava2.0在RxJava1.0的基礎(chǔ)對(duì)一些方法進(jìn)行了優(yōu)化,方便于開發(fā)者更好地理解其編程思想舀凛,同時(shí)又增加了一部分新的方法解決1.0存在的問(wèn)題俊扳,例如背壓等。所以猛遍,如果你學(xué)習(xí)過(guò)RxJava1.0那么很好馋记,你可能已經(jīng)理解了什么是觀察者模式碎绎;如果你沒(méi)有學(xué)過(guò)RxJava1.0,當(dāng)然也不必著急抗果,因?yàn)楸疚膶淖罨镜挠^察者模式講起,讓你從最基本最簡(jiǎn)單的角度入手RxJava奸晴。綜上所述冤馏,不管你是不是學(xué)過(guò)RxJava1.0,都不會(huì)影響你學(xué)習(xí)本篇文章。
觀察者模式
在學(xué)習(xí)RxJava2.0之前寄啼,我們必須要弄明白什么是觀察者模式逮光。按照我的慣例,先上一個(gè)百度百科的權(quán)威介紹
簡(jiǎn)單介紹一下墩划,A和B兩個(gè)涕刚,A是被觀察者,B是觀察者乙帮,B對(duì)A進(jìn)行觀察杜漠,B并不是需要時(shí)刻盯著A,而是A如果發(fā)生了變化察净,會(huì)主動(dòng)通知B驾茴,B會(huì)對(duì)應(yīng)做一些變化。舉個(gè)例子氢卡,假設(shè)A是連載小說(shuō)锈至,B是讀者,讀者訂閱了連載小說(shuō)译秦,當(dāng)小說(shuō)出現(xiàn)了新的連載的時(shí)候峡捡,會(huì)推送給讀者。讀者不用時(shí)刻盯著小說(shuō)連載筑悴,而小說(shuō)有了新的連載會(huì)主動(dòng)推送給讀者们拙。這就是觀察者模式。而RxJava正是基于觀察者模式開發(fā)的阁吝。
RxJava2.0的基本使用
理解好了觀察者模式睛竣,我們開始RxJava2.0的學(xué)習(xí)。首先引入RxJava2.0相關(guān)的類庫(kù)求摇。
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
正確使用姿勢(shì):
第一步:創(chuàng)建連載小說(shuō)(被觀察者)
//被觀察者
Observable novel=Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("連載1");
emitter.onNext("連載2");
emitter.onNext("連載3");
emitter.onComplete();
}
});
Observable中文意思就是被觀察者射沟,通過(guò)create方法生成對(duì)象,里面放的參數(shù)ObservableOnSubscribe<T>与境,可以理解為一個(gè)計(jì)劃表验夯,泛型T是要操作對(duì)象的類型,重寫subscribe方法摔刁,里面寫具體的計(jì)劃挥转,本文的例子就是推送連載1、連載2和連載3,在subscribe中的ObservableEmitter<String>對(duì)象的Emitter是發(fā)射器的意思绑谣。ObservableEmitter有三種發(fā)射的方法党窜,分別是void onNext(T value)、void onError(Throwable error)借宵、void onComplete()幌衣,onNext方法可以無(wú)限調(diào)用,Observer(觀察者)所有的都能接收到壤玫,onError和onComplete是互斥的豁护,Observer(觀察者)只能接收到一個(gè),OnComplete可以重復(fù)調(diào)用欲间,但是Observer(觀察者)只會(huì)接收一次楚里,而onError不可以重復(fù)調(diào)用,第二次調(diào)用就會(huì)報(bào)異常猎贴。
第二步:創(chuàng)建讀者(觀察者)
//觀察者
Observer<String> reader=new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
mDisposable=d;
Log.e(TAG,"onSubscribe");
}
@Override
public void onNext(String value) {
if ("2".equals(value)){
mDisposable.dispose();
return;
}
Log.e(TAG,"onNext:"+value);
}
@Override
public void onError(Throwable e) {
Log.e(TAG,"onError="+e.getMessage());
}
@Override
public void onComplete() {
Log.e(TAG,"onComplete()");
}
};
通過(guò)new創(chuàng)建接口班缎,并實(shí)現(xiàn)其內(nèi)部的方法,看方法其實(shí)就應(yīng)該差不多知道干嘛的她渴,onNext吝梅、onError、onComplete都是跟被觀察者發(fā)射的方法一一對(duì)應(yīng)的惹骂,這里就相當(dāng)于接收了苏携。onSubscribe(Disposable d)里面的Disposable對(duì)象要說(shuō)一下,Disposable英文意思是可隨意使用的对粪,這里就相當(dāng)于讀者和連載小說(shuō)的訂閱關(guān)系右冻,如果讀者不想再訂閱該小說(shuō)了,可以調(diào)用 mDisposable.dispose()取消訂閱著拭,此時(shí)連載小說(shuō)更新的時(shí)候就不會(huì)再推送給讀者了纱扭。
第三步:讀者和連載小說(shuō)建立訂閱關(guān)系
novel.subscribe(reader);//一行代碼搞定
在這里細(xì)心的你,可能已經(jīng)發(fā)現(xiàn)了怎么是小說(shuō)訂閱了讀者儡遮,之所以這樣乳蛾,是因?yàn)镽xJava主要是想保持自己的鏈?zhǔn)骄幊蹋坏貌话袿bservable(被觀察者)放在前面,這里大家可以理解為小說(shuō)被讀者訂閱了鄙币。
這里我們先看一下輸出效果
小結(jié)一下:這就是RxJava2.0最最簡(jiǎn)單的用法肃叶,創(chuàng)建小說(shuō),創(chuàng)建讀者十嘿,建立訂閱關(guān)系因惭,記住這三步,你就能實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的RxJava2.0的用法绩衷。
RxJava2.0的異步和鏈?zhǔn)骄幊?/h2>
前言里面有提到蹦魔,RxJava是支持異步的激率,但是RxJava是如何做到的呢?這里就需要Scheduler勿决。Scheduler乒躺,英文名調(diào)度器,它是RxJava用來(lái)控制線程低缩。當(dāng)我們沒(méi)有設(shè)置的時(shí)候嘉冒,RxJava遵循哪個(gè)線程產(chǎn)生就在哪個(gè)線程消費(fèi)的原則,也就是說(shuō)線程不會(huì)產(chǎn)生變化表制,始終在同一個(gè)。然后我們一般使用RxJava都是后臺(tái)執(zhí)行控乾,前臺(tái)調(diào)用么介,本著這個(gè)原則,我們需要調(diào)用observeOn(AndroidSchedulers.mainThread())蜕衡,observeOn是事件回調(diào)的線程壤短,AndroidSchedulers.mainThread()一看就知道是主線程,subscribeOn(Schedulers.io())慨仿,subscribeOn是事件執(zhí)行的線程久脯,Schedulers.io()是子線程,這里也可以用Schedulers.newThread()镰吆,只不過(guò)io線程可以重用空閑的線程帘撰,因此多數(shù)情況下 io() 比 newThread() 更有效率。前面的代碼根據(jù)異步和鏈?zhǔn)骄幊痰脑瓌t万皿,我們可以寫成
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("連載1");
emitter.onNext("連載2");
emitter.onNext("連載3");
emitter.onComplete();
}
})
.observeOn(AndroidSchedulers.mainThread())//回調(diào)在主線程
.subscribeOn(Schedulers.io())//執(zhí)行在io線程
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.e(TAG,"onSubscribe");
}
@Override
public void onNext(String value) {
Log.e(TAG,"onNext:"+value);
}
@Override
public void onError(Throwable e) {
Log.e(TAG,"onError="+e.getMessage());
}
@Override
public void onComplete() {
Log.e(TAG,"onComplete()");
}
});
這里就是RxJava最常用的寫法摧找,異步+鏈?zhǔn)骄幊蹋€要再說(shuō)一下牢硅,subscribe的方法重載蹬耘,subscribe()方法里什么參數(shù)也不放是空實(shí)現(xiàn),也就是說(shuō)連載小說(shuō)無(wú)論出什么連載减余,讀者都不關(guān)心综苔,推送過(guò)來(lái)了也不讀,如果讀者只關(guān)心onNext方法里的內(nèi)容位岔,可以直接重載subscribe(Consumer<? spuer T> onNext)這個(gè)方法如筛,會(huì)減少代碼,當(dāng)然如果是初學(xué)者還是建議創(chuàng)建Observer對(duì)象抒抬。
應(yīng)用場(chǎng)景
說(shuō)了這么多RxJava2.0的用法妙黍,你一定要問(wèn)了到底在什么情況下使用?下面先給大家介紹一下典型的場(chǎng)景瞧剖。
一拭嫁、與Retrofit聯(lián)用
Retrofit+RxJava的上網(wǎng)模式已經(jīng)非晨擅猓火了,如果有不了解的可以看筆者的這篇文章http://www.reibang.com/writer#/notebooks/5118090/notes/25405151
二做粤、Rxpermissions等類庫(kù)的使用
基于RxJava的開源類庫(kù)Rxpermissions浇借、RxBinding以及RxBus在很多項(xiàng)目中已經(jīng)非常常見,并且被證明了是極其好用的怕品。
三妇垢、所有用到異步的地方
因?yàn)镽xJava就是一個(gè)支持異步的鏈?zhǔn)骄幊蹋运械挠玫疆惒降牡胤饺饪担覀兌伎梢杂肦xJava來(lái)完成闯估,下面給大家舉幾個(gè)例子。
定時(shí)執(zhí)行任務(wù)
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(123);
sleep(3000);
emitter.onNext(456);
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.e(TAG,integer+"");
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
}
}, new Action() {
@Override
public void run() throws Exception {
}
});
看完上面的代碼你肯定在想吼和,這么多代碼涨薪,干嘛不直接new Handler().postDelayed()。如果你的程序線程里面做的操作很簡(jiǎn)單炫乓,那么你用new Handler().postDelayed()無(wú)所謂刚夺,但是如果你的操作很復(fù)雜,那么這時(shí)候就體現(xiàn)出了RxJava的好處了末捣,借用扔物線大神的一句話就是"隨著程序邏輯變得越來(lái)越復(fù)雜侠姑,RxJava依然能夠保持簡(jiǎn)潔"。
下面來(lái)說(shuō)一個(gè)復(fù)雜的操作箩做,比如我們要依次加載10張圖片(加載圖片是耗時(shí)過(guò)程)莽红,其中第六張我們延時(shí)3秒加載,第7張我們復(fù)制到sd卡里邦邦,第8張我們要上網(wǎng)絡(luò)船老,那么請(qǐng)問(wèn)你要怎么做,如果用Handler圃酵,必然是各種嵌套柳畔,各種邏輯復(fù)雜得讓你再看一眼都難受,但是如果使用RxJava呢郭赐?
Observable.create(new ObservableOnSubscribe<Drawable>() {
@Override
public void subscribe(ObservableEmitter<Drawable> emitter) throws Exception {
for (int i=0;i<drawableRes.length;i++){
Drawable drawable=getResources().getDrawable(drawableRes[i]);
//第6個(gè)圖片延時(shí)3秒后架子
if (i==5){
sleep(3000);
}
//復(fù)制第7張圖片到sd卡
if (i==6){
Bitmap bitmap=((BitmapDrawable)drawable).getBitmap();
saveBitmap(bitmap,"test.png", Bitmap.CompressFormat.PNG);
}
//上傳到網(wǎng)絡(luò)
if (i==7){
updateIcon(drawable);
}
emitter.onNext(drawable);
}
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Drawable>() {
@Override
public void accept(Drawable drawable) throws Exception {
//回調(diào)后在UI界面上展示出來(lái)
}
});
沒(méi)有任何嵌套薪韩,邏輯依然簡(jiǎn)潔,這就是RxJava的好處捌锭。
總結(jié)
RxJava2.0是非常好用的一個(gè)異步鏈?zhǔn)綆?kù)俘陷,遵循觀察者模式。理解觀察者模式可以根據(jù)連載小說(shuō)和讀者的關(guān)系观谦,被觀察者是連載小說(shuō)拉盾,觀察者是讀者,讀者訂閱小說(shuō)豁状,當(dāng)小說(shuō)有了新的連載推送給讀者捉偏,這就是觀察者模式倒得;創(chuàng)建RxJava最簡(jiǎn)單的步驟,一夭禽、創(chuàng)建被觀察者對(duì)象霞掺,二、創(chuàng)建觀者對(duì)象讹躯,三創(chuàng)建訂閱關(guān)系菩彬;RxJava2.0的應(yīng)用場(chǎng)景,只要記得一句話就是所有的異步都可以用RxJava來(lái)做就可以了潮梯,尤其是復(fù)雜的場(chǎng)景骗灶,越是復(fù)雜的場(chǎng)景越能體現(xiàn)RxJava的好處。關(guān)于RxJava的文章秉馏,筆者將會(huì)繼續(xù)推出兩篇耙旦,一篇是《RxJava從入門到進(jìn)階》講的是RxJava的一些進(jìn)階操作,例如變換沃饶、常用操作符和背壓母廷;另一篇是RxJava相關(guān)的類庫(kù)的介紹和使用轻黑,例如文章中提到的RxBinding糊肤、RxPerssions等等。如果喜歡筆者氓鄙,可以關(guān)注一波馆揉,謝謝!
最后放上我的github地址(本次demo的代碼基本都在文章上了抖拦,不下也可以):https://github.com/kaka10xiaobang/RxJavaDemo