RxJava2.0——從放棄到入門

前言

終于到了講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ā)的阁吝。


觀察者模式.png

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ì)象抒抬。


subscrib的方法重載

應(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末升酣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子态罪,更是在濱河造成了極大的恐慌噩茄,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件复颈,死亡現(xiàn)場(chǎng)離奇詭異绩聘,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)耗啦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門凿菩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人帜讲,你說(shuō)我怎么就攤上這事衅谷。” “怎么了似将?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵获黔,是天一觀的道長(zhǎng)蚀苛。 經(jīng)常有香客問(wèn)我,道長(zhǎng)肢执,這世上最難降的妖魔是什么枉阵? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮预茄,結(jié)果婚禮上兴溜,老公的妹妹穿的比我還像新娘。我一直安慰自己耻陕,他們只是感情好拙徽,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诗宣,像睡著了一般膘怕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上召庞,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天岛心,我揣著相機(jī)與錄音,去河邊找鬼篮灼。 笑死忘古,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诅诱。 我是一名探鬼主播髓堪,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼娘荡!你這毒婦竟也來(lái)了干旁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤炮沐,失蹤者是張志新(化名)和其女友劉穎争群,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體大年,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡换薄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鲜戒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片专控。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖遏餐,靈堂內(nèi)的尸體忽然破棺而出伦腐,到底是詐尸還是另有隱情,我是刑警寧澤失都,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布柏蘑,位于F島的核電站幸冻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏咳焚。R本人自食惡果不足惜洽损,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望革半。 院中可真熱鬧碑定,春花似錦、人聲如沸又官。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)六敬。三九已至碘赖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間外构,已是汗流浹背普泡。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留审编,地道東北人撼班。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像割笙,于是被迫代替她去往敵國(guó)和親权烧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子眯亦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,498評(píng)論 25 707
  • 前言 如果你對(duì)RxJava1.x還不是了解伤溉,可以參考下面文章。 1. RxJava使用介紹 【視頻教程】2. Rx...
    jdsjlzx閱讀 21,122評(píng)論 3 78
  • 前言 對(duì)于iOS App的開發(fā)妻率,幾乎都采用了Cocoapods來(lái)管理第三方庫(kù)乱顾,那么對(duì)于我們開發(fā)人員來(lái)說(shuō),這是必備技...
    面包與世界閱讀 347評(píng)論 0 0
  • 一生要經(jīng)歷多少離別才能不分離 分別的日子變得特別漫長(zhǎng)和遙遠(yuǎn) 在夢(mèng)里一遍又一遍地親吻你的眉和眼 為何你總是遲遲不歸來(lái)...
    Angel李子汐閱讀 394評(píng)論 18 40
  • 當(dāng)你在for循環(huán)里寫if判斷宫静,再加延時(shí)器或者定時(shí)器時(shí)走净,一定要保存當(dāng)前的i的值,再做處理孤里,否則你拿到的i的值會(huì)是fo...
    陽(yáng)光之城alt閱讀 1,917評(píng)論 0 1