徹底搞懂 RxJava — 高階篇
前言
本文獻給所有想要深入瞭解 RxJava 的人.
如果你還沒閱讀過基礎部分, 請先補習一下功課. 此外, 強烈建議你徹底理解中級部分再來閱讀本文.
本文將帶你理解 `.subscribeOn(Schedulers.io())` 和 `.observeOn(Schedulers.computation())` 用法背後的原理.
先看一下基本使用
我們來拆解一下 `.subscribeOn` 和 `.observeOn` 的作用範圍:
- `subscribeOn` 將作用於 `create` 中的 `OnSubscribe.call()` 方法.
- `observeOn` 作用於其語法中下一語句的 `Subscriber.onNext` 等函式中.
原始碼分析
首先分析 `subscribeOn`
與中級篇中的 `map` 一樣, 是通過建立了一個 `Observable` 來轉發 `OnSubscribe.call` 請求(程式碼中的 `OperatorSubscribeOn` 繼承自 `OnSubscribe`). 來看看具體實現(已略去無關程式碼):
1
2
3
4
5
6
7
8
9
|
public
void
call( final
Subscriber<? super
T> subscriber) { final
Worker inner = scheduler.createWorker(); inner.schedule( new
Action0() { @Override public
void
call() { source.unsafeSubscribe(s); } }); } |
可見, 該函式中做了如下兩件事:
- 建立一個用於在不同執行緒執行的 `Worker` 物件(程式碼中的 inner)
- 使用上述 `inner` 在該物件所代表的執行緒中執行 `Observable.onSubscribe.call` 方法(程式碼中的 `source.unsafeSubscribe(s);`
梳理一下 `SUBSCRIBEON` 的實現方法
再來分析稍微複雜一點兒的 `observeOn`
回顧一下 `LIFT`
1
2
3
4
5
6
7
|
public
final
<R> Observable<R> lift( final
Operator<? extends
R, ? super
T> operator) { return
new
Observable<R>( new
OnSubscribe<R>() { public
void
call(Subscriber<? super
R> o) { Subscriber<?
super
T> st = hook.onLift(operator).call(o);onSubscribe.call(st); } }); } |
`lift` 建立建立了一個 `Observable` 和 一個 `OnSubscriber` 物件. 而在 `OnSubscribe` 物件中又建立了一個 `Subscriber` (程式碼中的 `st`) 物件. 整個 `observeOn` 的重點也就在這個 `st` 物件中. 我們先來看一下 `st` 是如何生成的:
`hook.onLift(operator).call(o);` 實際上呼叫的就是 `operator.call(o)`. 而 `operator` 是 `OperatorObserveOn` 的例項. 所以看下 `OperatorObserveOn.call` 方法是如何生成 `st` 物件的(已略去無關程式碼):
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
Subscriber<? super
T> call(Subscriber<? super
T> child) { if
(scheduler instanceof
ImmediateScheduler) { //
avoid overhead, execute directly return
child; }
else
if
(scheduler instanceof
TrampolineScheduler) { //
avoid overhead, execute directly return
child; }
else
{ ObserveOnSubscriber<T>
parent = new
ObserveOnSubscriber<T>(scheduler, child, delayError); parent.init(); return
parent; } } |
該方法會根據 `scheduler` 的型別決定使用什麼方式返回 `Subscriber` 物件. 可見, 如果 child 型別為 `ImmediateScheduler` 或者 `TrampolineScheduler` 等以當前執行緒為執行環境的型別, 則直接返回 `child` 物件. 本例中, `child` 為 `NewThreadScheduler`, 因此將通過 `ObserveOnSubscriber` 對 `child` 進行包裝. 生成一個 proxy subscriber 物件.
至此, 我們可以知道 `observeOn` 是通過以下方法對其後面的 `Subscriber` 進行控制的:
- `lift` -> `OnSubscribe.call` -> `proxy subscriber = new Subscriber(original subscriber)` 建立了一個新的 `Subscriber`(實際上是個代理)
- 在上述 `proxy subscriber` 中對 `original subscriber` 物件的執行進行轉發. 轉發過程中, `proxy subscriber` 完全可以自由的控制 `original subscriber` 執行的執行緒.
整體梳理一下 `subscribeOn` + `observeOn` 的實現方法
Refs:
Grokking 帶你入門
Grokking RxJava, Part 1: The Basics
Grokking RxJava, Part 2: Operator, Operator
Grokking RxJava, Part 3: Reactive with Benefits
Grokking RxJava, Part 4: Reactive Android
Bruce 大頭鬼
RxJava基本流程和lift原始碼分析
讀原始碼!
ReactiveX/RxJava
walfud 徹底搞懂 RxJava 系列
徹底搞懂 RxJava — 初級篇
徹底搞懂 RxJava — 中級篇
徹底搞懂 RxJava — 高階篇
學以致用:
FlowImageLoader — 基於 RxJava 實現的圖片非同步載入庫. 該庫作者即 ‘徹底搞懂 RxJava 系列` 作者
Rx 規範
ReactiveX — An API for asynchronous programming (其中最有用的是 Contract)
其它
Awesome-RxJava
RxJava Essential CN (幫助你瞭解各種 Operator 的使用)
相關文章
- 徹底搞懂 RxJava — 基礎篇RxJava
- 徹底搞懂 RxJava — 中級篇RxJava
- 徹底搞懂 RxJavaRxJava
- 從原理到實戰,徹底搞懂Nginx(高階篇)Nginx
- 徹底搞懂徹底搞懂事件驅動模型 - Reactor事件模型React
- 徹底搞懂https原理HTTP
- 徹底搞懂JavaScript作用域JavaScript
- 徹底搞懂Bean載入Bean
- 徹底搞懂 Git-RebaseGit
- 深入JavaScript系列(四):徹底搞懂thisJavaScript
- 徹底搞懂 Channel 實現原理
- 徹底搞懂JavaScript中的繼承JavaScript繼承
- 徹底搞懂Python中的類Python
- 看完讓你徹底搞懂Websocket原理Web
- 兩萬字長文,徹底搞懂Kafka!Kafka
- 徹底搞懂JavaScript原型和原型鏈JavaScript原型
- 高頻面試題:一張圖徹底搞懂Spring迴圈依賴面試題Spring
- 混合移動App乾貨:一篇就可以徹底搞懂!APP
- 一篇文章徹底搞懂java動態代理的實現Java
- 徹底搞懂原型、原型鏈和繼承原型繼承
- 從原理到實戰,徹底搞懂NginxNginx
- Flutter(五)之徹底搞懂Dart非同步FlutterDart非同步
- 徹底搞懂瀏覽器Event-loop瀏覽器OOP
- 徹底搞懂Scrapy的中介軟體(三)
- 徹底搞懂Scrapy的中介軟體(二)
- 徹底搞懂Scrapy的中介軟體(一)
- 徹底搞懂HTTPS的加密機制HTTP加密
- 徹底搞懂Object和Function的關係ObjectFunction
- 一文徹底搞懂Raft演算法,看這篇就夠了!!!Raft演算法
- 一文徹底搞懂ZAB演算法,看這篇就夠了!!!演算法
- 兩張圖徹底搞懂MyBatis的Mapper原理!MyBatisAPP
- 這一次,徹底搞懂 Go CondGo
- 徹底搞懂容器技術的基石: namespace (下)namespace
- 徹底搞懂Composer自動載入原理
- 徹底搞懂同步非同步與阻塞非阻塞非同步
- 徹底搞懂 python 中文亂碼問題Python
- 看了這篇,我確定你已經徹底搞懂Java的繼承了Java繼承
- 徹底搞懂 MySQL 事務的隔離級別MySql