doOnSubscribe为何在主线程执行?与observeOn调度不符
为什么你的doOnSubscribe在主线程执行?
哈哈,这个坑我当初也踩过!确实很容易搞混doOnSubscribe的线程调度逻辑,我来给你掰扯清楚~
首先得先把subscribeOn和observeOn的核心作用区分开,这是理解问题的关键:
- subscribeOn:管的是「订阅发起」的线程,也就是你调用
subscribe()方法时所在的线程,同时它也会决定上游Observable(比如这里的just(1))的事件发射线程。而且subscribeOn是“一锤定音”的——整个序列里不管写多少个,只有第一个指定的线程会生效。 - observeOn:管的是「下游数据流处理」的线程,也就是它之后的操作符、subscribe回调的执行线程,这个可以多次切换,每调用一次observeOn,下游就会切换到对应的线程。
回到你的代码:
Observable.just(1) .observeOn(Schedulers.io()) .doOnSubscribe(__ -> Log.d("Testing", "Testing")) .subscribe();
这里的问题在于:doOnSubscribe的执行线程不遵循observeOn的调度!
因为doOnSubscribe是在「订阅事件发生时」触发的,而订阅事件的传递方向是从下游往上游走(你调用subscribe()后,订阅信号会一路传到最上游的Observable),这个过程完全发生在你调用subscribe()的线程(也就是主线程)上。observeOn只能管“事件发射之后的处理流程”,管不到“订阅发起”这个前置环节。
那如果想让doOnSubscribe在指定线程执行,有两个靠谱的办法:
- 用subscribeOn指定订阅线程(最常用的方式):
Observable.just(1) .subscribeOn(Schedulers.io()) // 这里指定订阅发起的线程,doOnSubscribe会跟着走这个线程 .doOnSubscribe(__ -> Log.d("Testing", "Testing")) .observeOn(AndroidSchedulers.mainThread()) // 如果下游需要切回主线程可以加这个 .subscribe();
- RxJava 2及以上版本,可以用doOnSubscribe的重载方法直接指定Scheduler:
Observable.just(1) .observeOn(Schedulers.io()) .doOnSubscribe(__ -> Log.d("Testing", "Testing"), Schedulers.io()) // 直接给doOnSubscribe指定线程 .subscribe();
总结一下:doOnSubscribe的线程由订阅发起的线程决定,也就是调用subscribe()的线程,或者通过subscribeOn/重载方法手动指定,和observeOn没有直接关系~
内容的提问来源于stack exchange,提问作者Dhruv Jagetiya
相关产品推荐
相关产品推荐

