前言
Scheduler 的 API
在RxJava 中,Scheduler ——調(diào)度器,相當于線程控制器,RxJava 通過它來指定每一段代碼應(yīng)該運行在什么樣的線程。
RxJava 已經(jīng)內(nèi)置了幾個 Scheduler ,它們已經(jīng)適合大多數(shù)的使用場景:
- Schedulers.immediate(): 直接在當前線程運行,相當于不指定線程。這是默認的 Scheduler。
- Schedulers.newThread(): 總是啟用新線程,并在新線程執(zhí)行操作。
- Schedulers.io(): I/O 操作(讀寫文件、讀寫數(shù)據(jù)庫、網(wǎng)絡(luò)信息交互等)所使用的 Scheduler。行為模式和 newThread() 差不多,區(qū)別在于 io() 的內(nèi)部實現(xiàn)是是用一個無數(shù)量上限的線程池,可以重用空閑的線程,因此多數(shù)情況下 io() 比 newThread() 更有效率。不要把計算工作放在 io() 中,可以避免創(chuàng)建不必要的線程。
- Schedulers.computation(): 計算所使用的 Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作,例如圖形的計算。這個 Scheduler 使用的固定的線程池,大小為 CPU 核數(shù)。不要把 I/O 操作放在 computation() 中,否則 I/O 操作的等待時間會浪費 CPU。
- AndroidSchedulers.mainThread(), Android 還有一個專用的 ,它指定的操作將在 Android 主線程運行。
有了這幾個 Scheduler ,就可以使用subscribeOn() 和 observeOn() 兩個方法來對線程進行控制了。
(1)subscribeOn(): 指定 subscribe() 所發(fā)生的線程,即 Observable.OnSubscribe 被激活時所處的線程。或者叫做事件產(chǎn)生的線程。
(2)observeOn(): 指定 Subscriber 所運行在的線程。或者叫做事件消費的線程。
線程操作的知識
先看兩個栗子:
栗子1
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
Logger.v( "rx_call" , Thread.currentThread().getName() );
subscriber.onNext( "dd");
subscriber.onCompleted();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(new Func1<String, String >() {
@Override
public String call(String s) {
Logger.v( "rx_map" , Thread.currentThread().getName() );
return s + "88";
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Logger.v( "rx_subscribe" , Thread.currentThread().getName() );
}
}) ;
結(jié)果
/rx_call: RxCachedThreadScheduler-1 --io線程
/rx_map: main --主線程
/rx_subscribe: main --主線程
栗子2
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
Logger.v( "rx_call" , Thread.currentThread().getName() );
subscriber.onNext( "dd");
subscriber.onCompleted();
}
})
.map(new Func1<String, String >() {
@Override
public String call(String s) {
Logger.v( "rx_map" , Thread.currentThread().getName() );
return s + "88";
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Logger.v( "rx_subscribe" , Thread.currentThread().getName() );
}
}) ;
結(jié)果
/rx_call: RxCachedThreadScheduler-1 --io線程
/rx_map: RxCachedThreadScheduler-1 --io線程
/rx_subscribe: main --主線程
分析上面兩個栗子,結(jié)論
- create() , just() , from() 等 --- 事件產(chǎn)生
- map() , flapMap() , scan() , filter() 等 -- 事件加工
- subscribe() -- 事件消費
事件產(chǎn)生:默認運行在當前線程,可以由 subscribeOn() 自定義線程
事件加工:默認跟事件產(chǎn)生的線程保持一致, 可以由 observeOn() 自定義線程
事件消費:默認運行在當前線程,可以有observeOn() 自定義
結(jié)論
subscribeOn 作用于該操作符之前的 Observable 的創(chuàng)建操符作以及 doOnSubscribe 操作符,換句話說就是 doOnSubscribe 以及 Observable 的創(chuàng)建操作符總是被其之后最近的 subscribeOn 控制。多次調(diào)用,創(chuàng)建操作符除了最近的外,其余無效。
observeOn() 設(shè)定事件加工和消費的線程,可以調(diào)用多次,每次調(diào)用只對后邊的操作產(chǎn)生影響。或者這樣說,observeOn作用于該操作符之后操作符直到出現(xiàn)新的observeOn操作符。
subscribeOn
查看log,這里,模塊3執(zhí)行,它后邊沒有設(shè)置線程,是main。
模塊2執(zhí)行,它后邊設(shè)置了IO線程,所以領(lǐng)打印“doOnSubscribe1:RxIoScheduler-2”
模塊1執(zhí)行,也就是創(chuàng)建create方法執(zhí)行,它后邊有兩個subscribeOn(),只有離他最近 的才會起作用。
observeOn
結(jié)論:observeOn作用于該操作符之后操作符直到出現(xiàn)新的observeOn操作符
圖片解釋:
圖中有兩個observeOn()方法,豎向的箭頭方向可以認為是Rxjava內(nèi)部變化方向,橫向的箭頭可以認為是程序執(zhí)行方向,顏色可以認為是不同的線程。
由圖可以看出,每次豎直方向經(jīng)過observeOn(),程序的執(zhí)行顏色都會變化為observeOn()設(shè)定的顏色,直到再次執(zhí)行observeOn()方法。
也就是 observeOn作用于該操作符之后操作符直到出現(xiàn)新的observeOn操作符
本文對應(yīng)源碼不做分析,只是講述結(jié)論性的知識。
歡迎繼續(xù)收看:RxJava入門與提高-網(wǎng)絡(luò)Retrofit 篇(5)
作者:ZhangYushui
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。