RxAndroid深入理解

mynk3578 8年前發布 | 23K 次閱讀 RxAndroid RxJava Android開發 移動開發

注:本文的分析基于RxAndroid 1.2.1

現在項目里面大多都已經使用了rxjava, 因此對于很多rxjava的擴展庫,也都可以使用在項目里了。

RxAndroid 已經成為標配了,基本只要使用了Rxjava, 你肯定能看見RxAndroid的身影。

使用場景:

Observable.just("one", "two", "three", "four", "five")
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(/* an Observer */);

很簡單,就是指定到主線程上,即UI線程上,所以subscribe里的內容就會執行在主線程上。

或者其他線程的Looper

Looper backgroundLooper = // ...
Observable.just("one", "two", "three", "four", "five")
        .observeOn(AndroidSchedulers.from(backgroundLooper))
        .subscribe(/* an Observer */)

這種使用方式,就是把后臺線程所綁定的Looper作為AndroidSchedulers的參數, 那么這時實際上等同于 :

...
observeOn(Scheduler.io());

因此這種方式下,subscribe 里的代碼是執行在backgroundLooper所綁定的線程。

代碼結構:

Paste_Image.png

實現分析:

既然使用的入口是AndroidScheduler 那就重這里開始分析。

首先看看AndroidScheduler的創建:

Paste_Image.png

搭眼一看,餓漢式的單例, 并且這個單例是使用AtomicReference的,原子操作,保證多線程情況下,線程獲取的值都是最新的,正確的。實例化用到了RxAndroidPlugins, 看下:

Paste_Image.png

同樣是AtomicReference ,同樣是單例。

Paste_Image.png

又引用到RxAndroidSechedulersHook

Paste_Image.png

這是個什么鬼,搞了半天最后getMainThreadScheduler() 返回null. 再回頭看看前面AndroidScheduler實例化的地方。

Paste_Image.png

soga, 空的話直接返回一個LooperScheduler, 否則直接使用。

這就是問題了,為什么要繞這么大一圈?

我覺得秘密在RxAndroidSchedulersHook里的一個方法,如下:

Paste_Image.png

那么這個方法在哪里被調用了呢? 這個問題先放著,后面會講到。

先來看看注釋,大概的意思是,該方法在把action 交給Scheduler處理之前被執行, 可以用于

包裝/裝飾/日志記錄(翻譯過來好別扭!), 默認值只是傳遞作用,直接返回。

如果你仔細看看Rxjava RxJavaSchedulersHook 類,你會發現如出一轍, 一模一樣!!!

連注釋都長一樣!

這里是把UI線程的Looper作為參數創建了一個LoopScheduler.

再進去看看LooperScheduler:

Paste_Image.png

LooperScheduler 繼承自Scheduler, 因此必須實現createWorker方法。

Worker是個什么東東?

Paste_Image.png

實際上是Scheduler里 的一個靜態抽象類,實現了Subscription接口,因此也就有unSubscriber方法。

可以取消訂閱,但是Worker并沒有實現取消訂閱方法,而是交給子類去實現,比如這里的HandlerWorker就實現了Worker抽象類,下面是截取的核心部分:

Paste_Image.png

HandlerWorker實現了schedule方法,一個是有延時的,一個是無延時的。 從代碼看首先判斷了是否被取消訂閱了, 取消了則直接返回,不做任何處理,否者接著走。

哎呦喂! 哎呦喂! 這不是RxAndroidSchedulersHook 里的那個我們之前放著的方法嗎?

在這里被調用了。

接著走這里又跳出來個ScheduledAction, 貼出代碼!

Paste_Image.png

Paste_Image.png

從代碼中不難看出, 在LooperScheduler 中創建的handler, 交給HandlerWorker后又交給了ScheduledAction。 該類實現了Runnable 接口,run方法里面調用了action.call() ;看來這里才是真正調用的地方,然后如果發生異常就調用RxjavaPlugin 觸發錯誤處理。

ScheduledAction同樣實現了Subscription接口, 取消也很簡單,handler removeCallbacks(this).。

看完了ScheduledAction是不是感覺一目了然了,接著上面HandlerWorker的schedule方法講,

后面從Message池中獲取了一個Message并且把message的Callback參數設置為ScheduledAction的實例, 然后后面handler.sendMessageDelayed(message, unit.toMillis(delayTime)); 延時發送這條消息。 看到這你應該明白了,就是利用handler把消息發送到了looper所在的線程! 因此你傳遞進去的Looper綁定在什么線程, 我們的action(訂閱者)就在哪個線程執行!

而我們平時都是使用AndroidScheduler.mainThread(); 默認傳遞的就是UI線程的Looper!

有的小伙伴說,不對吧,我沒看到接收處理消息的地方啊! 樓主你個坑!

實際上這就是handler你了解的不夠細:

(Handler.java)

Paste_Image.png

看到了嗎? 這里是handler接收到Looper分配的消息的處理, 先是判斷了msg有沒有callback, 有的話就不會調用handleMessage(msg)了,而是調用了handlerCallback(msg); 從而調用了runnable的run方法,也就是ScheduledAction的run()方法.

Paste_Image.png

RxAndroid中還有一個類沒講 MainThreadSubscription, 下篇文章會講下RxBinding,里面會講到,這里就不多說了。

 

 

來自:http://www.jianshu.com/p/8292ea39c38e

 

 本文由用戶 mynk3578 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!