RxJava學(xué)習(xí)筆記(解讀源碼)

寫(xiě)在前面的話

看了源碼也不少,但是每次看源碼都僅僅鸵鸥,也就是僅僅跟著作者一步步跟進(jìn)ta的方法疾宏,點(diǎn)進(jìn)去施绎,再點(diǎn)進(jìn)去惧财,再再點(diǎn)進(jìn)去,漸漸的感覺(jué)自己當(dāng)時(shí)看的太膚淺摊崭,有很多問(wèn)題都會(huì)冒出來(lái),最多的就是為什么要這樣寫(xiě)呢杰赛,一追究這個(gè)問(wèn)題就會(huì)發(fā)現(xiàn)自己在知識(shí)的海洋里是如此的渺小呢簸。寫(xiě)了這么多,希望能夠在以后眼光放高一些乏屯,看大局根时,看別人是如何排兵布陣!

rxjava執(zhí)行原理

先從調(diào)用rxjava功能的代碼入手辰晕,首先最簡(jiǎn)單的調(diào)用就是:

Observable.create(new Observable.OnSubscribe<Integer>() {//創(chuàng)建

    @Override
    public void call(Subscriber<? super Integer> subscriber) {
        subscriber.onNext(1);
        subscriber.onCompleted();
    }

}).subscribe(new Observer<Integer>() {

    @Override
    public void onCompleted() {
        System.out.println("Completed");
    }

    @Override
    public void onError(Throwable e) {
        System.out.println("Error");
    }

    @Override
    public void onNext(Integer integer) {
        System.out.println("i = " + integer);
    }
});

Observable.create()

  • 首先調(diào)用Observable.create()創(chuàng)建一個(gè)生產(chǎn)者Observable,同時(shí)創(chuàng)建了一個(gè)OnSubscribe作為其參數(shù)傳給Observable

  • OnSubscribeObservable的一個(gè)內(nèi)部接口蛤迎,從它的注釋"* Invoked when Observable.subscribe is called."可以看出當(dāng)生產(chǎn)者被消費(fèi)者訂閱的時(shí)候,它將會(huì)被激活含友。

  • 再看方法內(nèi)部:

      public static <T> Observable<T> create(OnSubscribe<T> f) {
          return new Observable<T>(RxJavaHooks.onCreate(f));
      }
    
  • 接著我們看到創(chuàng)建的OnSubscribe又傳入了RxJavaHooks.onCreate(f)中:

      public static <T> Observable.OnSubscribe<T> onCreate(Observable.OnSubscribe<T> onSubscribe) {
          Func1<Observable.OnSubscribe, Observable.OnSubscribe> f = onObservableCreate;
          if (f != null) {
              return f.call(onSubscribe);
          }
          return onSubscribe;
      }
    
  • 這里判斷了RxJavaHooks中的成員變量onObservableCreate是否為空忘苛,在RxjavaHooks的內(nèi)部有一個(gè)靜態(tài)方法initCreate()可以對(duì)其進(jìn)行初始化,但是我們并沒(méi)有調(diào)用它唱较,所有我們最后返回的onSubscribe依然還是我們自己創(chuàng)建的onSubscribe扎唾。

  • 倒回至Observable的構(gòu)造函數(shù),最后將這個(gè)onSubscribe賦值給了Observable的成員變量南缓。

      protected Observable(OnSubscribe<T> f) {
          this.onSubscribe = f;
      }
    

Subscriber

創(chuàng)建了生產(chǎn)者Observable胸遇,那么肯定還要?jiǎng)?chuàng)建消費(fèi)者ObserverSubscriber就是Observer接口的一個(gè)實(shí)現(xiàn)類(lèi)汉形,同時(shí)還實(shí)現(xiàn)了Subscription接口纸镊,這個(gè)接口的方法unsubscribe()用于取消訂閱,還有一個(gè)isUnsubscribed()方法判斷訂閱的狀態(tài)概疆,unsubscribe() 這個(gè)方法很關(guān)鍵逗威,因?yàn)樵?subscribe()之后, Observable 會(huì)持有 Subscriber 的引用岔冀,這個(gè)引用如果不能及時(shí)被釋放凯旭,將有內(nèi)存泄露的風(fēng)險(xiǎn)。

subscribe()

  • 接下來(lái)就是subscribe()方法:

      static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
          // new Subscriber so onStart it
          subscriber.onStart();
    
          if (!(subscriber instanceof SafeSubscriber)) {
              subscriber = new SafeSubscriber<T>(subscriber);
          }
    
          try {
              RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);
              return RxJavaHooks.onObservableReturn(subscriber);
          } catch (Throwable e) {
                  ...
              }
              return Subscriptions.unsubscribed();
          }
      }
    
  • 首先subscriber = new SafeSubscriber<T>(subscriber)會(huì)將我們自己寫(xiě)的subscriber進(jìn)行包裝使套,其實(shí)也就是代理的設(shè)計(jì)模式罐呼,在我們寫(xiě)的代碼中通過(guò)代理進(jìn)行一些安全校驗(yàn),這里就保證了onCompleted()onError()只會(huì)有一個(gè)執(zhí)行切只執(zhí)行一次侦高。

  • 接著看RxJavaHooks.onObservableStart(observable, observable.onSubscribe)就會(huì)發(fā)現(xiàn)嫉柴,同樣該方法返回的就是我們創(chuàng)建的onSubscribe,之后還調(diào)用了它的call()方法奉呛,也就成了
    調(diào)用我們自己寫(xiě)的call()方法计螺。

  • call()方法中的參數(shù)subscriber其實(shí)就是我們?cè)谡{(diào)用subscribe()訂閱時(shí)夯尽,作為參數(shù)傳進(jìn)來(lái)的subscriber,這樣也就讓我們?cè)谏a(chǎn)者這里調(diào)用到了消費(fèi)者的方法登馒,這樣也就達(dá)到了觀察者的目的匙握。

rxjava變換原理

rxjava的變換雖然功能各有不同,但實(shí)質(zhì)上都是針對(duì)時(shí)間序列的處理和再發(fā)送谊娇,這里我們就通過(guò)map()來(lái)了解其中的原理肺孤,一下就是利用map的一段代碼:

Observable.just(1,2,3)
        .map(new Func1<Integer, String>() {
            @Override
            public String call(Integer integer) {
                return "i = " + integer;
            }
        })
        .subscribe(new Observer<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {
                System.out.println("s : " + s);
            }
        });

接著看map()方法:

public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
    return create(new OnSubscribeMap<T, R>(this, func));
}

是不是感覺(jué)很熟悉罗晕,返回的就是創(chuàng)建Observable的方法济欢,也就是說(shuō)它將我們map()中的func作為onSubscribeMap的構(gòu)造參數(shù),那么onSubscribeMap又是什么小渊,它其實(shí)就是OnSubscribe的一個(gè)實(shí)現(xiàn)類(lèi)法褥,先看其構(gòu)造方法:

public OnSubscribeMap(Observable<T> source, Func1<? super T, ? extends R> transformer) {
    this.source = source;
    this.transformer = transformer;
}

這里通過(guò)內(nèi)部的成員變量保存了傳遞進(jìn)來(lái)的ObservableFunc1,記住酬屉,這里也就是說(shuō)在外頭調(diào)用該方法的Observable半等,也就是源Observable保存在了source,而我們?cè)?code>map()中寫(xiě)的Func1()保存在了transformer中呐萨,在往后看.subscribe()杀饵,注意調(diào)用訂閱方法的已經(jīng)不是源Observable,而是通過(guò)map()內(nèi)部自己創(chuàng)建返回的一個(gè)新Observable谬擦,也就是說(shuō)新的Observable持有了Subscriber的對(duì)象切距,那么,訂閱了之后自然就會(huì)激活Observable發(fā)射數(shù)據(jù)惨远,也就是onSubscribe中的call()方法開(kāi)始執(zhí)行谜悟,在這里就是onSubscribeMapcall()方法。

public void call(final Subscriber<? super R> o) {
    MapSubscriber<T, R> parent = new MapSubscriber<T, R>(o, transformer);
    o.add(parent);
    source.unsafeSubscribe(parent);
}

代碼開(kāi)頭就創(chuàng)建了一個(gè)MapSubscriber北秽,它是Subscriber的一個(gè)子類(lèi)葡幸,構(gòu)造函數(shù)如下:

public MapSubscriber(Subscriber<? super R> actual, Func1<? super T, ? extends R> mapper) {
    this.actual = actual;
    this.mapper = mapper;
}

聯(lián)系上頭代碼,可以發(fā)現(xiàn)它將傳入的Subscriber包裝成了MapSubscriber贺氓,同時(shí)還講源SubscriberFunc1保存在了成員變量中蔚叨,之后執(zhí)行的時(shí)候肯定要執(zhí)行onNext()方法,直接看onNext()

public void onNext(T t) {
    R result;

    try {
        result = mapper.call(t);
    } catch (Throwable ex) {
        Exceptions.throwIfFatal(ex);
        unsubscribe();
        onError(OnErrorThrowable.addValueAsLastCause(ex, t));
        return;
    }

    actual.onNext(result);
}

這里有一個(gè)泛型R辙培,也就是返回值類(lèi)型缅叠,是通過(guò)構(gòu)造函數(shù)傳入的,最重要的代碼result = mapper.call(t)虏冻,這里的mapper就是我們?cè)?code>map()中寫(xiě)的Func1肤粱,接著傳入?yún)?shù),通過(guò)我們自己的方法得到我們想要的結(jié)果返回厨相。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末领曼,一起剝皮案震驚了整個(gè)濱河市鸥鹉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌庶骄,老刑警劉巖毁渗,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異单刁,居然都是意外死亡灸异,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)羔飞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)肺樟,“玉大人,你說(shuō)我怎么就攤上這事逻淌∶床” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵卡儒,是天一觀的道長(zhǎng)田柔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)骨望,這世上最難降的妖魔是什么硬爆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮擎鸠,結(jié)果婚禮上缀磕,老公的妹妹穿的比我還像新娘。我一直安慰自己糠亩,他們只是感情好虐骑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著赎线,像睡著了一般廷没。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上垂寥,一...
    開(kāi)封第一講書(shū)人閱讀 51,115評(píng)論 1 296
  • 那天颠黎,我揣著相機(jī)與錄音,去河邊找鬼滞项。 笑死狭归,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的文判。 我是一名探鬼主播过椎,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼戏仓!你這毒婦竟也來(lái)了疚宇?” 一聲冷哼從身側(cè)響起亡鼠,我...
    開(kāi)封第一講書(shū)人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎敷待,沒(méi)想到半個(gè)月后间涵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡榜揖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年勾哩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片举哟。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡思劳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出炎滞,到底是詐尸還是另有隱情敢艰,我是刑警寧澤诬乞,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布册赛,位于F島的核電站,受9級(jí)特大地震影響震嫉,放射性物質(zhì)發(fā)生泄漏森瘪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一票堵、第九天 我趴在偏房一處隱蔽的房頂上張望扼睬。 院中可真熱鬧,春花似錦悴势、人聲如沸窗宇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)军俊。三九已至,卻和暖如春捧存,著一層夾襖步出監(jiān)牢的瞬間粪躬,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工昔穴, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留镰官,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓吗货,卻偏偏與公主長(zhǎng)得像泳唠,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宙搬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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