作者: @怪盜kidou
如需轉(zhuǎn)載需在明顯位置保留作者信息及原文鏈接
如果博客中有不恰當(dāng)之處歡迎留言交流
http://www.lxweimin.com/p/59c3d6bb6a6b
前言
距離上次寫(xiě)博客又是一個(gè)多月了,這次來(lái)聊一聊 RxJava 的線程變換,即 observeOn(Scheduler) 和 subscribeOn(Scheduler) 的作用范圍。
為什么要做線程變換
最最簡(jiǎn)單的例子就是 Anroid 中數(shù)據(jù)獲取、處理需要在后臺(tái)進(jìn)行,而展示的過(guò)程則需要在UI線程中執(zhí)行,如果你沒(méi)有搞懂 observeOn 和 subscribeOn 的作用范圍,那你以后寫(xiě)程序的時(shí)候 Crash 就會(huì)對(duì)你不棄不離了,當(dāng)然了你讀了這篇博客就可以很輕松搞定了!
observeOn
先說(shuō)結(jié)論:observeOn作用于該操作符之后操作符直到出現(xiàn)新的observeOn操作符
舉個(gè)例子:
Observable.just("RxJava")
.observeOn(getNamedScheduler("map之前的observeOn"))
.map(s -> {
threadInfo(".map()-1");
return s + "-map1";
})
.map( s -> {
threadInfo(".map()-2");
return s + "-map2";
})
.observeOn(getNamedScheduler("subscribe之前的observeOn"))
.subscribe(s -> {
threadInfo(".onNext()");
System.out.println(s + "-onNext");
});
結(jié)果如下:
.map()-1 => map之前的observeOn
.map()-2 => map之前的observeOn
.onNext() => subscribe之前的observeOn
RxJava-map1-map2-onNext
observeOn作用域圖示:
subscribeOn
同樣先說(shuō)結(jié)論:subscribeOn 作用于該操作符之前的 Observable 的創(chuàng)建操符作以及 doOnSubscribe 操作符 ,換句話說(shuō)就是 doOnSubscribe 以及 Observable 的創(chuàng)建操作符總是被其之后最近的 subscribeOn 控制 。沒(méi)看懂不要緊,看下面代碼和圖你就懂了。
舉個(gè)例子:
Observable
.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
threadInfo("OnSubscribe.call()");
subscriber.onNext("RxJava");
}
})
.subscribeOn(getNamedScheduler("create之后的subscribeOn"))
.doOnSubscribe(() -> threadInfo(".doOnSubscribe()-1"))
.subscribeOn(getNamedScheduler("doOnSubscribe1之后的subscribeOn"))
.doOnSubscribe(() -> threadInfo(".doOnSubscribe()-2"))
.subscribe(s -> {
threadInfo(".onNext()");
System.out.println(s + "-onNext");
});
結(jié)果如下:
.doOnSubscribe()-2 => main
.doOnSubscribe()-1 => doOnSubscribe1之后的subscribeOn
OnSubscribe.call() => create之后的subscribeOn
.onNext() => create之后的subscribeOn
RxJava-onNext
subscribeOn作用域圖示:
3號(hào)框中的.doOnSubscribe(() -> threadInfo(".doOnSubscribe()-2"))
的之后由于沒(méi)有subscribeOn
操作符所以回調(diào)在該段代碼被調(diào)用的線程(即主線程)
由于 subscribe 之前 沒(méi)有 使用observeOn 指定Scheduler,所以.onNext()
的線程是和OnSubscribe.call()
使用相同的Scheduler 。
其它說(shuō)明
博文中所謂的 之后、之前 不代表中間沒(méi)有其它操作符。
doOnSubscribe
與onStart
類(lèi)似,均在代碼調(diào)用時(shí)就會(huì)回調(diào),但doOnSubscribe
可以通過(guò)subscribeOn
操作符改變運(yùn)行的線程且越在后面運(yùn)行越早。
本文中用到的其它方法
public static Scheduler getNamedScheduler(String name) {
return Schedulers.from(Executors.newCachedThreadPool(r -> new Thread(r, name)));
}
public static void threadInfo(String caller) {
System.out.println(caller + " => " + Thread.currentThread().getName());
}
我最近剛剛開(kāi)通了微信公眾號(hào)(怪盜kidou),歡迎關(guān)注