RXjava observeOn subscribeOn 解析

1 篇文章 0 订阅

RXjava 中的observeOn subscribeOn 两个函数十分类似,相信很多人在使用时会有疑问。官方文档的说明,包括图片不是那么容易理解,特此立翻译贴一篇。

官方文档解释如下地址:

http://reactivex.io/documentation/operators/observeon.html

http://reactivex.io/documentation/operators/subscribeon.html


=================================    observeOn 篇   ========================================

指定观察者运行的Scheduler(Scheduler即指定的所在线程)

ObserveOn

(图片解释:重点是箭头,初始化黑色箭头代表默认线程,调用observeOn方法 黄色箭头指定Scheduler,所以下面的箭头都变成了黄色,即改变了代码运行所在的线程)


很多基于ReactiveX 的实现使用Schedulers来控制一个被观察者在多个线程之间切换。你可以通过observeOn操作来指定一个Scheduler,命令一个被观察者通过此Scheduler发送通知给观察者。

ObserveOn and SubscribeOn

(图解:这个图很牛逼!先表扬一下......我们从上往下看,初始化(xian)箭(cheng)头颜色不再跟第一张图是黑色的了,而是蓝色的,我们发现下面有个subscribeOn 方法是指定蓝色(xian)箭(cheng)头的,没错,原因就在这里,具体为什么等会翻译subscribeOn的时候再说。然后是一个observeOn方法指定黄色(xian)箭(cheng)头,然后是一个map操作,(xian)箭(cheng)头是黄色的,然后是subscribeOn操作,暂时略过,最后又是observeOn操作,指定的是粉色(xian)箭(cheng)头,这个操作之后,黄色(xian)箭(cheng)头变为了粉色(xian)箭(cheng)头。)


subscribeOn操作是类似的,但是subscribeOn是控制被观察者在哪一个Scheduler上执行自身的操作(onsubscribe的call方法)以及通知观察者的操作(onNext,onCompleted,map等)。


默认情况下,被观察者以及被观察者的调用链操作会在调用subscribe方法的线程上执行。subscribeOn操作能指定一个特殊的Scheduler,从而改变这个行为,使被观察者的操作在这个Scheduler上执行。observeOn操作指定一个不同的Scheduler,被观察者会在这个Scheduler上发送通知给观察者。


在上述图中,subscribeOn操作指定被观察者在哪一个线程执行操作,不论在调用链中哪一个位置调用这个方法。

observeOn影响observeOn操作之后的被观察者运行的线程。因为这个原因,你可以在调用链中多次调用observeOn来达到改变运行的所在线程。


=================================    subscribeOn篇   ========================================

指定被观察者运行的Scheduler

SubscribeOn

(图解:区别上一篇,在调用subscribeOn方法后,初始化的线程也是黄色箭头的,所以两者的区别在于作用域不同,subscribeOn影响整个被观察者的运行所在线程,observeOn影响的是observeOn操作后的代码)


很多基于ReactiveX 的实现使用Schedulers来控制一个被观察者在多个线程之间切换。你可以通过subscribeOn操作来指定一个Scheduler,命令一个被观察者通过此Scheduler执行工作。(对比上文observeOn中此处的解释,理解他们之间的区别)


observeOn操作也是相似的,但是observeOn操作局限性大一点。observeOn仅仅影响被观察者在哪个Schedulers上发送通知给观察者。

(接下去的内容跟observeOn篇是一样的)


==========================================   补充   =========================================

看完文章,我们明白observeOn可以多次调用,调度不同线程执行操作,但对于subscribeOn多次调用的情况下会如何,官方文档中并未提及。

从源码中分析,subscribeOn会生成一个新的被观察者对象,老的被观察者会被新对象持有,类似包装类模式,新对象对老对象的操作就是将老对象丢到指定的新线程中去执行,所以!不管你调用几次subscribeOn,最终还是会回到第一次调用subscribeOn指定的线程中去。(包装类不管包装几次,一次一次往里调用,最终还是会调用到最根本的那一个类中去)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RxJava中的flatMap操作符是一个非常常用的操作符,它可以将一个Observable发射的事件序列转换成多个Observables,然后将这些Observables发射的事件序列合并后再发射出去。 下面是flatMap操作符的源码解析: ```java public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) { ObjectHelper.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableFlatMap<>(this, mapper, false, Integer.MAX_VALUE, bufferSize())); } ``` 可以看到,flatMap操作符的实现是通过创建一个ObservableFlatMap对象来完成的。其中,mapper参数表示将原始Observable发射的事件转换成的新Observable,它是一个Function类型的参数,即接受一个T类型的参数并返回一个ObservableSource类型的结果。 ObservableFlatMap的构造函数如下所示: ```java ObservableFlatMap(ObservableSource<T> source, Function<? super T, ? extends ObservableSource<? extends R>> mapper, boolean delayErrors, int maxConcurrency, int bufferSize) { this.source = source; this.mapper = mapper; this.delayErrors = delayErrors; this.maxConcurrency = maxConcurrency; this.bufferSize = bufferSize; } ``` ObservableFlatMap的核心实现是在subscribeActual方法中完成的: ```java @Override public void subscribeActual(Observer<? super R> observer) { if (ObservableScalarXMap.tryScalarXMapSubscribe(source, observer, mapper)) { return; } source.subscribe(new FlatMapObserver<>(observer, mapper, delayErrors, maxConcurrency, bufferSize)); } ``` 在subscribeActual方法中,首先判断源Observable是否可以直接转换为ObservableScalarXMap,如果可以的话直接进行转换,否则创建一个FlatMapObserver对象并进行订阅。 FlatMapObserver是flatMap的核心实现类,它实现了Observer接口,并且在接收到源Observable发射的事件时,会先将事件转换成新的Observable,然后将新Observable的发射事件序列合并到一个新的Observable中,最后再将新的Observable发射出去。 ```java static final class FlatMapObserver<T, R> extends AtomicInteger implements Observer<T>, Disposable { // ... @Override public void onNext(T t) { ObservableSource<? extends R> o; try { o = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper returned a null ObservableSource"); } catch (Throwable e) { Exceptions.throwIfFatal(e); upstream.dispose(); onError(e); return; } if (cancelled) { return; } if (maxConcurrency != Integer.MAX_VALUE) { synchronized (this) { if (wip == maxConcurrency) { queue.offer(t); return; } wip++; } } o.subscribe(new InnerObserver(inner, delayErrors, this)); } // ... } ``` 在FlatMapObserver的onNext方法中,首先调用mapper将源Observable发射的事件转换成新的Observable,并进行非空检查。然后判断当前的并发度是否达到了最大值,如果达到了最大值,就将源Observable发射的事件放到队列中。否则,就将并发度加1,并订阅新Observable。 InnerObserver是FlatMapObserver的内部类,它实现了Observer接口,并在接收到来自新Observable的发射事件序列时,将它们合并到一个新的Observable中,并将新的Observable发射出去。 ```java static final class InnerObserver<R> implements Observer<R> { // ... @Override public void onNext(R t) { if (done) { return; } inner.onNext(t); } // ... } ``` 当所有的新Observable都完成后,FlatMapObserver会调用onComplete方法通知观察者。如果发生了异常,FlatMapObserver会调用onError方法通知观察者。同时,FlatMapObserver还实现了Disposable接口,可以通过dispose方法取消订阅。 综上所述,flatMap操作符的实现是比较复杂的,它通过创建ObservableFlatMap对象,并在subscribeActual方法中创建FlatMapObserver对象来完成转换操作。在FlatMapObserver中,它还需要实现对新Observable的订阅以及将新Observable发射的事件合并到一个新的Observable中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值