目錄
一、Is what 是什么
二、Concept 概念
三、Basic realization 基本實(shí)現(xiàn)
四、Scheduler 線程控制(上)
五、Scheduler 線程控制(下)
六、變換
因個(gè)人學(xué)習(xí)需要,故文章內(nèi)容均為網(wǎng)上摘抄整理,感謝創(chuàng)作者的辛勤,源文章地址請(qǐng)看文末。
API(二)
通過subscribeOn()和observeOn()控制線程,讓事件的產(chǎn)生和消費(fèi)發(fā)生在不同的線程。同樣,在使用變換的方法(map()、flatMap())時(shí),可以多次切換線程。
線程多次切換
observeOn() 指定的是Subscriber的線程,而這個(gè)Subscriber并不是(嚴(yán)格說應(yīng)為『不一定是』)subscriber()參數(shù)中的Subscriber,而是observeOn()執(zhí)行時(shí)的當(dāng)前Observable所對(duì)應(yīng)的Subscriber,即它的直接下級(jí)Subscriber。換句話說,observeOn()指定的是它之后的操作所在的線程。因此如果有多次切換線程的需求,只要在每個(gè)切換線程的位置調(diào)用一次observeOn()即可,示例如下:
Observable.just(1, 2, 3, 4) // IO 線程,由 subscribeOn() 指定
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.map(mapOperator) // 新線程,由 observeOn() 指定
.observeOn(Schedulers.io())
.map(mapOperator2) // IO 線程,由 observeOn() 指定
.observeOn(AndroidSchedulers.mainThread)
.subscribe(subscriber); // Android 主線程,由 observeOn() 指定
不同于
observeOn(),subscribeOn()的位置放在哪里都可以,只被調(diào)用一次。
含多個(gè)subscribeOn()時(shí),只有第一個(gè)會(huì)起作用。
Scheduler 的原理(二)
subscribeOn()和observeOn()的內(nèi)部實(shí)現(xiàn),是用lift()。
subscribeOn()示意圖:

observeOn()示意圖:

相同點(diǎn):subscribeOn()和observeOn()都做了線程切換的操作(圖中"schedule..."部分)。
不同點(diǎn):
-
subscribeOn()的線程切換發(fā)生在OnSubscribe中,即在它通知上一級(jí)OnSubscribe時(shí),此時(shí)事件還沒有開始發(fā)送,因此subscribeOn()的線程控制可以從事件發(fā)出的開端就造成影響; -
observaOn()的線程切換發(fā)生在它內(nèi)建的Subscriber中,即發(fā)生在它即將給下級(jí)Subscriber發(fā)送事件時(shí),因此observeOn()控制的是它后面的線程。
下面用一張圖來解釋當(dāng)多個(gè) subscribeOn() 和 observeOn() 混合使用時(shí),線程調(diào)度是怎么發(fā)生的:

圖中含 5 處對(duì)事件的操作:
①和②兩處受第一個(gè) subscribeOn() 影響,運(yùn)行在紅色線程;
③和④處受第一個(gè) observeOn() 影響,運(yùn)行在綠色線程;
⑤處受第二個(gè) observeOn() 影響,運(yùn)行在紫色線程;
第二個(gè) subscribeOn() ,由于在通知過程中線程就被第一個(gè) subscribeOn() 截?cái)啵虼藢?duì)整個(gè)流程并沒有任何影響。
doOnSubscribe()
雖然超過一個(gè)的subscribeOn()對(duì)事件處理的流程沒有影響,但在流程之前卻可以利用。
因?yàn)?code>Subscriber的onStart()可以用作流程開始前的初始化,而onStart()在subscribe()發(fā)生時(shí)就被調(diào)用了,因此不能指定線程,只能執(zhí)行在subscribe()被調(diào)用時(shí)的線程。試想,如果onStart()中含有對(duì)線程有要求的代碼(例:在界面顯示ProgressBar,必須在主線程執(zhí)行),將會(huì)有線程非法的風(fēng)險(xiǎn),因?yàn)橛袝r(shí)無法預(yù)測(cè)subscribe()將會(huì)在什么線程執(zhí)行。
與Subscriber.onStart()相對(duì)應(yīng)的方法Observable.doOnSubscribe()。和Subscriber.onStart()同樣是在sbscribe()調(diào)用后且事件發(fā)送前執(zhí)行,區(qū)別在于可以指定線程。
- 默認(rèn)情況:
doOnSubscribe()執(zhí)行在subscribe()發(fā)生的線程; -
doOnSubscribe()后有subscribeOn()時(shí),將執(zhí)行在離他最近的subscribeOn()所指定的線程。
示例:
Observable.create(onSubscribe)
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Action0() {
@Override
public void call() {
progressBar.setVisibility(View.VISIBLE); // 需要在主線程執(zhí)行
}
})
.subscribeOn(AndroidSchedulers.mainThread()) // 指定主線程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);