# RxJava 源碼分析

引言

簡(jiǎn)單闡述RxJava流程源碼,RxJava有以下三種流程,向下遞增挽绩。

  • Observable->Observer
  • Observable->Operator->Observer
  • Observable->Operator->Scheduler->Observer

簡(jiǎn)單流程

先看一下RxJava簡(jiǎn)單的代碼:

Observable.create(new Observable.OnSubscribe<Boolean>() {
        @Override
        public void call(Subscriber<? super Boolean> s) {
            s.onNext(true);
            s.onCompleted();
        }
    }).subscribe(new Observer<Boolean>() {

                @Override
                public void onCompleted() {
                    _log("On complete");
                    _progress.setVisibility(View.INVISIBLE);
                }

                @Override
                public void onError(Throwable e) {
                    Timber.e(e, "Error in RxJava Demo concurrency");
                    _log(String.format("Boo! Error %s", e.getMessage()));
                    _progress.setVisibility(View.INVISIBLE);
                }

                @Override
                public void onNext(Boolean bool) {
                    _log(String.format("onNext with return value \"%b\"", bool));
                }
            });

據(jù)上:Obervable create傳入Observable.OnSubscribe作為參數(shù)膛壹。OnSubscribe 會(huì)被存儲(chǔ)在返回的 Observable 對(duì)象中,它的作用相當(dāng)于一個(gè)計(jì)劃表唉堪,當(dāng)Observable被訂閱的時(shí)候模聋,即當(dāng)Obervable.subscribe(observer)的時(shí)候,OnSubscribe 的 call() 方法會(huì)自動(dòng)被調(diào)用,事件序列就會(huì)依照設(shè)定依次觸發(fā)唠亚。

看下subscribe method 源碼

rxjava_subscribe.jpg

將源碼簡(jiǎn)化一下就是這樣:

public Subscription subscribe(Subscriber subscriber) {
  subscriber.onStart();//可選的準(zhǔn)備方法
  onSubscribe.call(subscriber);//開始執(zhí)行計(jì)劃表
  return subscriber;//返回Subscription 方便unsubscribe()
}

你會(huì)發(fā)現(xiàn)觸發(fā)Observable的時(shí)間是subscribe產(chǎn)生訂閱關(guān)系的時(shí)候链方。
另外你會(huì)看到subscribe中參數(shù)是Subscriber類型,Subscriber是實(shí)現(xiàn)Oberver的抽象類。

帶有Operator的流程

這里我們說的Operator是一種抽象的概念,上述簡(jiǎn)單流程中我們是手寫計(jì)劃表OnSubscribe,而這里我們不需要,我們只需要調(diào)用just,map,等轉(zhuǎn)換操作,這些操作內(nèi)部幫我們實(shí)現(xiàn)了OnSubscribe計(jì)劃表,我將這些操作稱之為Operator.

我們看一下帶有Operator的簡(jiǎn)單代碼:

Observable.just(true).map(new Func1<Boolean, Boolean>() {
        @Override
        public Boolean call(Boolean aBoolean) {
            _log("Within Observable");
            _doSomeLongOperation_thatBlocksCurrentThread();
            return aBoolean;
        }
    }).subscribe(new Observer<Boolean>() {

        @Override
        public void onCompleted() {
            _log("On complete");
            _progress.setVisibility(View.INVISIBLE);
        }

        @Override
        public void onError(Throwable e) {
            Timber.e(e, "Error in RxJava Demo concurrency");
            _log(String.format("Boo! Error %s", e.getMessage()));
            _progress.setVisibility(View.INVISIBLE);
        }

        @Override
        public void onNext(Boolean bool) {
            _log(String.format("onNext with return value \"%b\"", bool));
        }
    });

據(jù)上:和第一種簡(jiǎn)單流程的代碼相比,subscribe之后的代碼是一致的,不同的是subscribe之前的代碼趾撵。兩個(gè)方法just和map method,通過源碼分析下功能侄柔。

  • just method
rxjava_just_method.jpg
rxjava_ScalarSynchronousObservable.jpg

just function:將傳入的參數(shù)發(fā)送給Subscriber訂閱者。
你可以根據(jù)上面ScalarSynchronousObservable的構(gòu)造函數(shù),重寫OnSubscribe計(jì)劃表看出來占调。

  • map method
rxjava_map.jpg

rxjava_lift_method.jpg

rxjava_OperatorMap.jpg

將上面代碼簡(jiǎn)化就是:

public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
return Observable.create(new OnSubscribe<R>() {
    @Override
    public void call(Subscriber subscriber) {
        Subscriber newSubscriber = operator.call(subscriber);//通過Operator創(chuàng)建一個(gè)新的Subscriber,通過OperatorMap將新舊Subscriber建立一種關(guān)系暂题。
        newSubscriber.onStart();//準(zhǔn)備操作
        onSubscribe.call(newSubscriber);//onSubscribe計(jì)劃表喚醒新的Subscriber,新的Subscriber會(huì)聯(lián)系subscribe訂閱的Subscriber(訂閱者)。
    }
});
}   

借助拋物線文章中的圖抽象表現(xiàn)出來:

rxjava_map_pic.jpg

再帶上Scheduler的流程

Scheduler function:指明Observable和Observer是運(yùn)行在哪個(gè)線程中究珊。

  • subscribeOn指定的是Observable(被觀察者)所在線程
  • observeOn指定的是Observer(觀察者)所在線程

我們?cè)趲в蠴perator的基礎(chǔ)上加上Scheduler.

Observable.just(true).map(new Func1<Boolean, Boolean>() {
        @Override
        public Boolean call(Boolean aBoolean) {
            _log("Within Observable");
            _doSomeLongOperation_thatBlocksCurrentThread();
            return aBoolean;
        }
    }).subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread()).subscribe(...)

observeOn與subscribeOn也是通過lift變換原理實(shí)現(xiàn)線程切換, observeOn切換線程是發(fā)生在lift方式中的內(nèi)建的Subscriber中,subscribeOn切換線程是發(fā)生在OnSubscribe計(jì)劃表中薪者。

調(diào)度器源碼我也沒太搞明白,以后有機(jī)會(huì)補(bǔ)上。不過調(diào)度器作為RxJava的一大特性,在Android編程中使用非常方便。

總結(jié)

  • RxJava最核心流程是Observable->Oberver 當(dāng)subscribe訂閱的時(shí)候,不管增加怎樣復(fù)雜的變化,一定是OnSubscribe計(jì)劃表來通知觀察者,被觀察者發(fā)生變化。
  • RxJava靈活的特性主要在兩個(gè)方面,數(shù)據(jù)序列的變化機(jī)制和線程切換成畦。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市悬槽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瞬浓,老刑警劉巖初婆,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡磅叛,警方通過查閱死者的電腦和手機(jī)屑咳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弊琴,“玉大人兆龙,你說我怎么就攤上這事∏枚” “怎么了紫皇?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長臣缀。 經(jīng)常有香客問我坝橡,道長泻帮,這世上最難降的妖魔是什么精置? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮锣杂,結(jié)果婚禮上脂倦,老公的妹妹穿的比我還像新娘。我一直安慰自己元莫,他們只是感情好赖阻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著踱蠢,像睡著了一般火欧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茎截,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天苇侵,我揣著相機(jī)與錄音,去河邊找鬼企锌。 笑死榆浓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的撕攒。 我是一名探鬼主播陡鹃,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼抖坪!你這毒婦竟也來了萍鲸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤擦俐,失蹤者是張志新(化名)和其女友劉穎脊阴,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹬叭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年藕咏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秽五。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡孽查,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出坦喘,到底是詐尸還是另有隱情盲再,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布瓣铣,位于F島的核電站答朋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏棠笑。R本人自食惡果不足惜梦碗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蓖救。 院中可真熱鬧洪规,春花似錦、人聲如沸循捺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽从橘。三九已至念赶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間恰力,已是汗流浹背叉谜。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牺勾,地道東北人正罢。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像驻民,于是被迫代替她去往敵國和親翻具。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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