如上,通过 observeOn()
的多次调用,程序实现了线程的多次切换。
不过,不同于 observeOn()
, subscribeOn()
的位置放在哪里都可以,但它是只能调用一次的。
又有好事的(其实还是当初的我)问了:如果我非要调用多次 subscribeOn()
呢?会有什么效果?
这个问题先放着,我们还是从 RxJava 线程控制的原理说起吧。
2) Scheduler 的原理
其实, subscribeOn()
和 observeOn()
的内部实现,也是用的 lift()
。具体看图(不同颜色的箭头表示不同的线程):
subscribeOn()
原理图:
observeOn()
原理图:
从图中可以看出,subscribeOn()
和 observeOn()
都做了线程切换的工作(图中的 “schedule…” 部位)。不同的是, subscribeOn()
的线程切换发生在 OnSubscribe
中,即在它通知上一级 OnSubscribe
时,这时事件还没有开始发送,因此 subscribeOn()
的线程控制可以从事件发出的开端就造成影响;而 observeOn()
的线程切换则发生在它内建的 Subscriber
中,即发生在它即将给下一级 Subscriber
发送事件时,因此 observeOn()
控制的是它后面的线程。
最后,我用一张图来解释当多个 subscribeOn()
和 observeOn()
混合使用时,线程调度是怎么发生的(由于图中对象较多,相对于上面的图对结构做了一些简化调整):
图中共有 5 处含有对事件的操作。由图中可以看出,①和②两处受第一个 subscribeOn()
影响,运行在红色线程;③和④处受第一个 observeOn()
的影响,运行在绿色线程;⑤处受第二个 onserveOn()
影响,运行在紫色线程;而第二个 subscribeOn()
,由于在通知过程中线程就被第一个 subscribeOn()
截断,因此对整个流程并没有任何影响。这里也就回答了前面的问题:当使用了多个 subscribeOn()
的时候,只有第一个 subscribeOn()
起作用。
3) 延伸:doOnSubscribe()
然而,虽然超过一个的 subscribeOn()
对事件处理的流程没有影响,但在流程之前却是可以利用的。
在前面讲 Subscriber
的时候,提到过 Subscriber
的 onStart()
可以用作流程开始前的初始化。然而 onStart()
由于在 subscribe()
发生时就被调用了,因此不能指定线程,而是只能执行在 subscribe()
被调用时的线程。这就导致如果 onStart()
中含有对线程有要求的代码(例如在界面上显示一个 ProgressBar,这必须在主线程执行),将会有线程非法的风险,因为有时你无法预测 subscribe()
将会在什么线程执行。
而与 Subscriber.onStart()
相对应的,有一个方法 Observable.doOnSubscribe()
。它和 Subscriber.onStart()
同样是在 subscribe()
调用后而且在事件发送前执行,但区别在于它可以指定线程。默认情况下, doOnSubscribe()
执行在 subscribe()
发生的线程;而如果在 doOnSubscribe()
之后有 subscribeOn()
的话,它将执行在离它最近的 subscribeOn()
所指定的线程。
示例代码:
Observable.create(onSubscribe)
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Action0() {
@Override
public void call() {
progressBar.setVisibility(View.VISIBLE); // 需要在主线程执行
}
})
.subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
如上,在 doOnSubscribe()
的后面跟一个 subscribeOn()
,就能指定准备工作的线程了。
原文链接https://gank.io/post/560e15be2dca930e00da1083#toc_17
最后笔者收集整理了一份Flutter高级入门进阶资料PDF
以下是资料目录和内容部分截图
里面包括详细的知识点讲解分析,带你一个星期入门Flutter。还有130个进阶学习项目实战视频教程,让你秒变大前端。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
-F1xFMoMf-1715140483793)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!