RxAndroid深入理解
注:本文的分析基于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