RxJava学习笔记4

这里我们再来深入学习一下RxJava的线程调度,在RxJava学习笔记2中简单对RxJava中的线程调度进行了简单的使用介绍,这里我么继续深入线程调度在RxJava中的提现

可以利用 subscribeOn() 结合 observeOn() 来实现线程控制,让事件的产生和消费发生在不同的线程。可是在了解了 map() flatMap() 等变换方法后,内部出现了不少的Obserable,自然会多出了不少的发送事件和消费事件,那么能不能多切换几次线程?

回答是肯定的。因为 observeOn() 指定的是 Subscriber 消费的线程,而这个 Subscriber 并不是(严格说应该为『不一定是』,但这里不妨理解为『不是』)subscribe() 参数中的 Subscriber ,

而是 observeOn() 执行时的当前 Observable 所对应的 Subscriber ,即它的直接下级 Subscriber

换句话说,observeOn() 指定的是它之后的操作所在的线程。因此如果有多次切换线程的需求,只要在每个想要切换线程的位置调用一次 observeOn() 即可。上代码:

Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定
    .subscribeOn(Schedulers.io()) //指定 解析 1234的发生线程

    .observeOn(Schedulers.newThread()) //指定直接下级的直接线程
    .map(mapOperator) // 新线程,由 observeOn() 指定 

    .observeOn(Schedulers.io())  //直接指定下级的直接线程
    .map(mapOperator2) // IO 线程,由 observeOn() 指定

    .observeOn(AndroidSchedulers.mainThread) //直接指定下级的直接线程


和observeOn()相比较 ,
 subscribeOn() 的位置放在哪里都可以,但它是只能调用一次的。

这里写图片描述

图中的 schedule…就是线程调度的地方

subscribeOn() 的线程切换发生在 OnSubscribe 中,即在它通知上一级 OnSubscribe 时,这时事件还没有开始发送,因此 subscribeOn() 的线程控制可以从事件发出的开端就造成影响;

observeOn() 的线程切换则发生在它内建的 Subscriber 中,即发生在它即将给下一级 Subscriber 发送事件时,因此 observeOn() 控制的是它后面的线程。

我们再回过头 看一眼 多次 执行subscribeOn()会有什么后果。

这里写图片描述

图中共有 5 处含有对事件的操作。由图中可以看出,
①和②两处受第一个 subscribeOn() 影响,运行在红色线程;
③和④处受第一个 observeOn() 的影响,运行在绿色线程;
⑤处受第二个 onserveOn() 影响,运行在紫色线程;

而第二个 subscribeOn() ,由于在通知过程中线程就被第一个 subscribeOn() 截断,因此对整个流程并没有任何影响。这里也就回答了前面的问题:当使用了多个 subscribeOn() 的时候,只有第一个 subscribeOn() 起作用。


延伸: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() {
        public void call() {
            progressBar.setVisibility(View.VISIBLE); // 需要在主线程执行
        }
    })
    .subscribeOn(AndroidSchedulers.mainThread()) 
    // 指定主线程 >>通过在这里指定 使得 上面一段代码的线程可以发生在主线程中 >>>>这是个实用的技巧 请记住 
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(subscriber);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值