RxJava 2.x入門新姿勢一

引言

經(jīng)過幾年的發(fā)展般妙,響應式編程已經(jīng)是很流行了陈哑,在Android開發(fā)中的應用也非常的廣泛合瓢,身為Android開發(fā)者,則是必須掌握的技術杨凑。

正文

網(wǎng)上已經(jīng)有很多很多RxJava相關的文章滤奈,視頻等等教程,但是說實話對于入門撩满,或者新手來說蜒程,確實不好理解绅你,上來就是各種,觀察者昭躺、被觀察者忌锯、訂閱、發(fā)布等等概念领炫,一遍看下來直接就暈了偶垮,就感覺RxJava很難,難理解帝洪,用的時候也只是依葫蘆畫瓢似舵,暈乎乎的用著,然后就沒有然后了碟狞。

這里我都不說那些概念啄枕,因為講概念太抽象,難記住族沃,更難理解频祝。我們用另外一個視角來學習。因為RxJava 1.x的版本 官方已經(jīng)停止更新了維護了脆淹,沒有學習過也沒有關系常空,RxJava 2.x是全新的,直接學習使用就好了盖溺。

首先假設我們在工廠里上班漓糙,工廠都會有流水線,產(chǎn)品經(jīng)過流水線生產(chǎn)后來訂單了銷售出去烘嘱。


事件處理模型

這里假設工廠生產(chǎn)的是一種六邊形的“Jerry帥氣餅干”昆禽,上游是生產(chǎn)車間流水線的事件流,下游是訂單產(chǎn)品的銷售消費事件流蝇庭。中間連接上下游關系的暫且叫做“Jerry帥氣餅干生產(chǎn)消費訂單管理系統(tǒng)”(不要臉醉鳖,名字寫這么長),為了下文方便抒寫且用“生產(chǎn)訂單管理系統(tǒng)”(PCMS)哮内。以上圖上下游對應的就是Obsersvable被觀察者也是發(fā)布者盗棵,下游對應Observer觀察者也是訂閱者。使用RxJava代碼表示上圖就是:

public void test1() {

        // 上游生成產(chǎn)品流水線
        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                Log.d(TAG, "test1 ====== Observable: ------ onNext: Jerry");
                emitter.onNext("Jerry");
                Log.d(TAG, "test1 ====== Observable: ------ onNext: 就是");
                emitter.onNext("就是");
                Log.d(TAG, "test1 ====== Observable: ------ onNext: 帥");
                emitter.onNext("帥");
                Log.d(TAG, "test1 ====== Observable: ------ onNext: 1狈ⅰN埔颉!");
                emitter.onNext("A詹Α2t恰。?);
                Log.d(TAG, "test1 ====== Observable: ------ onComplete");
                emitter.onComplete();
                Log.d(TAG, "test1 ====== Observable: ------ onNext: Jerry帥炸天S印>贰是牢!");
                emitter.onNext("Jerry帥炸天!I陆亍!");
            }
        });

        // 下游訂單產(chǎn)品銷售
        Observer<String> observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "test1 ====== Observer: onSubscribe");
            }

            @Override
            public void onNext(String value) {
                Log.d(TAG, "test1 ====== Observer: onNext: " + value);
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "test1 ====== Observer: onError: " + e.getMessage());
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "test1 ====== Observer: onComplete");
            }
        };

        // 連接上下游的訂單管理系統(tǒng)
        observable.subscribe(observer);
    }

上述代碼批什,上游生產(chǎn)車間流水線就是Observable农曲,下游訂單銷售就是Observer,中間通過“生產(chǎn)訂單管理系統(tǒng)”subscribe來將上下游連接起來驻债。

運行后輸出結果是:


輸出結果

從輸出結果來看乳规,當上游Observable發(fā)出一個生產(chǎn)的餅干產(chǎn)品事件,下游訂單銷售的Observer就銷售一個餅干產(chǎn)品事件合呐,而且當上游調(diào)用了onComplete方法后暮的,上游的生產(chǎn)事件還是生產(chǎn)餅干事件(繼續(xù)生產(chǎn)了“Jerry帥炸天”餅干事件),但是下游的訂單銷售卻沒有消費掉淌实。也就是事件產(chǎn)生方調(diào)用onComplete方法后冻辩,之后的事件還會繼續(xù)發(fā)送,但是事件接收方就不會接收了拆祈。

我們來看看Observable的subscribe方法的參數(shù):ObservableEmitter恨闪,Emitter顧名思義是發(fā)射器的意思,ObservableEmitter接口繼承自Emitter接口:

public interface Emitter<T> {

    /**
     * Signal a normal value.
     * @param value the value to signal, not null
     */
    void onNext(T value);

    /**
     * Signal a Throwable exception.
     * @param error the Throwable to signal, not null
     */
    void onError(Throwable error);

    /**
     * Signal a completion.
     */
    void onComplete();
}

接口定義很簡單放坏,就三個方法咙咽,onNext我們上門已經(jīng)用過了,是用來發(fā)射發(fā)送事件的淤年,onComplete是用來表示事件發(fā)送完了钧敞,后面如果有新的事件發(fā)送,下游接收者可以不用處理麸粮,onError方法看注釋說是發(fā)送一個異常事件給下游接收者溉苛。到底是不是這樣,我們來試試就曉得了豹休。

public void test2() {

        // 上游生成產(chǎn)品流水線
        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                Log.d(TAG, "test2 ====== Observable: ------ onNext: Jerry");
                emitter.onNext("Jerry");
                Log.d(TAG, "test2 ====== Observable: ------ onNext: 就是");
                emitter.onNext("就是");
                Log.d(TAG, "test2 ====== Observable: ------ onNext: 帥");
                emitter.onNext("帥");
                Log.d(TAG, "test2 ====== Observable: ------ onNext: 4独ァ!威根!");
                emitter.onNext("7锞蕖!洛搀!");
                Log.d(TAG, "test2 ====== Observable: ------ onError");
                emitter.onError(new IllegalStateException("Jerry餅干烤焦了敢茁,賣出去會被打!"));
                Log.d(TAG, "test2 ====== Observable: ------ onNext: Jerry帥炸天A裘馈U妹省伸刃!");
                emitter.onNext("Jerry帥炸天!7瓯丁捧颅!");
            }
        });

        // 下游訂單產(chǎn)品銷售
        Observer<String> observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "test2 ====== Observer: onSubscribe");
            }

            @Override
            public void onNext(String value) {
                Log.d(TAG, "test2 ====== Observer: onNext: " + value);
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "test2 ====== Observer: onError: " + e.getMessage());
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "test2 ====== Observer: onComplete");
            }
        };

        // 連接上下游的訂單管理系統(tǒng)
        observable.subscribe(observer);
    }

在上游生產(chǎn)餅干的時候就生產(chǎn)了一個“Jerry餅干烤焦了,賣出去會被打较雕!”的錯誤餅干事件碉哑,下游訂單銷售的onError出錯狀態(tài)會消費這個事件。而上游在出錯事件后發(fā)送的“Jerry帥炸天A两?鄣洹!”餅干事件慎玖,同樣也只是把事件發(fā)送了處理贮尖,下游訂單銷售并沒有接收處理這個事件。

運行后輸出結果:


輸出結果

細心的小伙伴應該會發(fā)現(xiàn)趁怔,每次執(zhí)行的時候都會先調(diào)用下游的onSubscribe方法湿硝,這個方法里有個參數(shù)Disposable(用完即可丟棄)意思可以理解成,將上下游的連接切斷痕钢,讓上游的生產(chǎn)的餅干不打包放入下游訂單銷售環(huán)節(jié)图柏,實際開發(fā)中是有這種需求的,當發(fā)送事件出問題的時候就需要斷開事件接收處理任连。不像最近的疫苗事件蚤吹,一些不要臉的生物疫苗公司把生產(chǎn)不合格的疫苗上市銷售,傷天害理随抠,謀財害命裁着。下面舉個例子:

public void test3() {

        // 上游生成產(chǎn)品流水線
        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                Log.d(TAG, "test3 ====== Observable: ------ onNext: Jerry");
                emitter.onNext("Jerry");
                Log.d(TAG, "test3 ====== Observable: ------ onNext: 就是");
                emitter.onNext("就是");
                Log.d(TAG, "test3 ====== Observable: ------ onNext: 帥");
                emitter.onNext("帥");
                Log.d(TAG, "test3 ====== Observable: ------ onNext: !9八二驰!");
                emitter.onNext("!1印桶雀!");
                Log.d(TAG, "test3 ====== Observable: ------ onComplete");
                emitter.onComplete();
                Log.d(TAG, "test3 ====== Observable: ------ onNext: Jerry帥炸天!;8础矗积!");
                emitter.onNext("Jerry帥炸天!3ㄟ帧棘捣!");
            }
        });

        // 下游訂單產(chǎn)品銷售
        Observer<String> observer = new Observer<String>() {

            private Disposable mDisposable;
            private int i;

            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "test3 ====== Observer: onSubscribe");
                mDisposable = d;
            }

            @Override
            public void onNext(String value) {
                Log.d(TAG, "test3 ====== Observer: onNext: " + value);
                i++;
                // 第一個事件接收后,就斷開上下游連接
                if (i == 1) {
                    Log.d(TAG, "test3 ====== Observer: start disposable");
                    mDisposable.dispose();
                    Log.d(TAG, "test3 ====== Observer: isDisposable: " + mDisposable.isDisposed());
                }
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "test3 ====== Observer: onError: " + e.getMessage());
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "test3 ====== Observer: onComplete");
            }
        };

        // 連接上下游的訂單管理系統(tǒng)
        observable.subscribe(observer);
    }

這里我們在下游訂單銷售的onNext方法中休建,當接收完第一個餅干事件后乍恐,就使用mDisposable.dispose()方法將上下游的連接斷開了评疗,斷開后上游后續(xù)生產(chǎn)的餅干事件,下游就接收不到茵烈。

運行的結果:


image.png

上圖中百匆,也驗證了我們的猜想,當使用dispose斷開上下游連接后呜投,下游就無法再繼續(xù)接收事件了胧华。


這一講就先介紹這么多,這樣的方式理解Observable和Observer以及訂閱動作subscribe是不是容易多了宙彪,希望對你有所幫助,下一講使用RxJava來切換變化餅干事件處理的線程(主線程有巧、子線程)释漆。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市篮迎,隨后出現(xiàn)的幾起案子男图,更是在濱河造成了極大的恐慌,老刑警劉巖甜橱,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逊笆,死亡現(xiàn)場離奇詭異,居然都是意外死亡岂傲,警方通過查閱死者的電腦和手機难裆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來镊掖,“玉大人乃戈,你說我怎么就攤上這事∧督” “怎么了症虑?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長归薛。 經(jīng)常有香客問我谍憔,道長,這世上最難降的妖魔是什么主籍? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任习贫,我火速辦了婚禮,結果婚禮上崇猫,老公的妹妹穿的比我還像新娘沈条。我一直安慰自己,他們只是感情好诅炉,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布蜡歹。 她就那樣靜靜地躺著屋厘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪月而。 梳的紋絲不亂的頭發(fā)上汗洒,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天,我揣著相機與錄音父款,去河邊找鬼溢谤。 笑死,一個胖子當著我的面吹牛憨攒,可吹牛的內(nèi)容都是我干的世杀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼肝集,長吁一口氣:“原來是場噩夢啊……” “哼瞻坝!你這毒婦竟也來了?” 一聲冷哼從身側響起杏瞻,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤所刀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后捞挥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浮创,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年砌函,在試婚紗的時候發(fā)現(xiàn)自己被綠了斩披。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡讹俊,死狀恐怖雏掠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情劣像,我是刑警寧澤乡话,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站耳奕,受9級特大地震影響绑青,放射性物質發(fā)生泄漏。R本人自食惡果不足惜屋群,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一闸婴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧芍躏,春花似錦邪乍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽榜配。三九已至,卻和暖如春吕晌,著一層夾襖步出監(jiān)牢的瞬間蛋褥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工睛驳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留烙心,地道東北人。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓乏沸,卻偏偏與公主長得像淫茵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蹬跃,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

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

  • 怎么如此平靜, 感覺像是走錯了片場.為什么呢, 因為上下游工作在同一個線程呀騷年們! 這個時候上游每次調(diào)用emit...
    Young1657閱讀 1,472評論 2 1
  • 轉載自:https://xiaobailong24.me/2017/03/18/Android-RxJava2.x...
    Young1657閱讀 2,022評論 1 9
  • 引入依賴: implementation 'io.reactivex.rxjava2:rxandroid:2.0....
    為夢想戰(zhàn)斗閱讀 1,304評論 0 0
  • 觀察者模式的運用 傳統(tǒng)的Java觀察者模式可以參考此篇博客:Java觀察者模式案例簡析 RxJava 是基于Jav...
    正規(guī)程序員閱讀 2,633評論 0 52
  • 學習寫作良久痘昌,斷斷續(xù)續(xù)地也寫了些文章。每當靈感來臨之際炬转,總會提筆寫上幾文。一次算灸,把文章拿給精于寫作的老師看扼劈,他認認...
    熊一一閱讀 1,527評論 0 1