轻松搞懂subscribeOn与observeOn

319 阅读2分钟

最近发现组内有同学把Rxjava的subscribeOn跟observeOn用反,导致了线上事故,想起了自己很早写的一篇文章,今天就把这老掉牙的文章搬运到掘金来。

在使用Rxjava的时候,总是不知道该用subscribeOn还是observeOn,死记硬背不仅容易忘并且还容易记错,接下来我们从原理出发,一文搞懂这两个的区别,再也不会出错。

讲解正文之前,我们先看一下核心类图。构成了Rxjava的蛇形调用(其实就是观察者模式的变种,将观察者模式的观察者设置为另外一个观察者模式的被观察者)。

subscribeActual是Observable的核心,所有Observable的特殊实现都是在这个方法里。

示例:假设mapper与observer1里的代码是我们的业务代码。

image.png 可以看出,Rxjava在调用的过程就像下面的图形一样。侧过来看就是“S”型调用(蛇形)

第1条线:执行链式调用

第2条线:执行框架层代码与subcribeOn

第3条线:我们的核心代码,比如上图中的map与observer1

暂时无法在飞书文档外展示此内容

根据上图可以清晰的看明白,在执行我们的核心代码第3条链路之前,不管有多少个subscribeOn,只有第一个subscribeOn是生效的,而observerOn是针对下面的代码生效。

image.png

源码分析:

我们先看subscribeOn对应的代码

//Observable.java

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> subscribeOn(Scheduler scheduler) {
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}

// ObservableSubscribeOn.java

public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    ...
    @Override
    public void subscribeActual(final Observer<? super T> observer) {
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(observer);
        observer.onSubscribe(parent);
        parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
    }
  }
  //SubscribeTask.java
  
  static final class SubscribeTask<T> implements Runnable {
    final MaybeObserver<? super T> observer;
    final MaybeSource<T> source;

    SubscribeTask(MaybeObserver<? super T> observer, MaybeSource<T> source) {
        this.observer = observer;
        this.source = source;
    }

    @Override
    public void run() {
        source.subscribe(observer);
    }
}

我们再看observeOn的源码

//Observable.java

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    ObjectHelper.verifyPositive(bufferSize, "bufferSize");
    return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
}

//ObservableObserveOn.java

public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
    ...

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        
            Scheduler.Worker w = scheduler.createWorker();
            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize);
        }
 }

从代码上可以看到,subscribeOn 与 observeOn的主要区别就是,subscribeOn先切换了线程再执行的source.subscribe(这个方法是向上回溯的,每个observable都会调用,只有这个方法执行完之后,才会执行我们自己的代码)。