Android RxJava2 源码解析

一、前言


关于 RxJava 的使用推荐大家看这篇文章 RxJava2 只看这一篇文章就够了

 

二、订阅


 首先我们先分析一个最简单的示例,代码如下:

        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("1");
                emitter.onNext("2");
                emitter.onNext("3");
                emitter.onComplete();
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.e("TAG", "onSubscribe():  ");
            }

            @Override
            public void onNext(String s) {
                Log.e("TAG", "onNext():  " + s);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
                Log.e("TAG", "onComplete():  ");
            }
        });

既然要了解 RxJava,那么必不可少的我们应该先来看看他的入口类,也就是 Observable

//Observable.java
public abstract class Observable<T> implements ObservableSource<T> {
    @Override  //实现了ObservableSource的方法
    public final void subscribe(Observer<? super T> observer) {
        //省略一堆判空等处理 
        subscribeActual(observer);
    }

    @Override  //交由子类实现的出现方法
    protected abstract void subscribeActual(Observer observer) ;
}

省略了一堆静态方法之后我们可以看到 Observable 是一个抽象类,实现了 ObservableSource 接口,并留了 subscribeActual() 这个抽象方法。ObservableSource 接口只定义了一个 subscribe() 方法,可以看到这个方法做了一些基础判断之后直接跳转到子类的 subscribeActual() 方法。所以一个被观察者被 subscribe() 的逻辑其实是交由 Observable 子类来实现的,每个不同的被观察者可以根据自己的需求实现 "被订阅" 后的操作。

接下来是如何生成一个 Obserable 对象,我们看到 create() 方法。create() 方法便是 Obserable 其中一个关键的静态方法。我们跟进去看一下 create() 方法源码:

//Observable.java
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
    ObjectHelper.requireNonNull(source, "source is null");
    return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}

首先第一句代码是对传入的对象进行判空,内部实现是如果传入 null 会抛异常。接着是生成一个 ObservableCreate 对象,然后将这个对象传入 RxJavaPlugins 进行组装。RxJavaPlugins 提供了一系列的 Hook function,通过钩子函数这种方法对 RxJava 的标准操作进行加工,当我们没有进行配置时,默认是直接返回原来的对象,也就是返回 ObservableCreate 对象。(为了方便讲解,后续将直接忽视判空和 RxJavaPlugins 的代码)

//ObservableCreate.java
public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        observer.onSubscribe(parent);

        try {
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }

从上述方法可以看出 ObservableCreate 是 Observable 的一个子类,我们自定义的 ObservableOnSubscribe 作为一个名为 source 字段被传入了。事实上在 Observable 的子类实现中,它们都有一个名为 source 的字段,指代上游 Observable(实际上是 ObservableOnSubscribe,但是我们不妨理解成就是 Observable)。

我们看下 subcribeActual() 方法中第 1 行代码的 CreateEmitter:

//ObservableCreate.java
    static final class CreateEmitter<T>
    extends AtomicReference<Disposable>
    implements ObservableEmitter<T>, Disposable {

        private static final long serialVersionUID = -3434801548987643227L;

        final Observer<? super T> observer;

        CreateEmitter(Observer<? super T> observer) {
            this.observer = observer;
        }

        @Override
        public void onNext(T t) {
            if (t == null) {
                onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
                return;
            }
            if (!isDisposed()) {
                observer.onNext(t);
            }
        }
        ......

可以看到 CreateEmitter 实现了 ObservableEmitter 和 Disposable 接口。

在 subscribeActual() 的第 5 行调用了 Observer#onSubscribe(Disposable) ,所以我们可以知道 Observer#onSubscribe(Disposable) 是先被调用的,而此时 Observable 甚至还没有开始发射事件!接下来就是调用了 source.subscribe(ObservableEmitter),这个方法是交由开发者去实现的,在示例代码是如下:

@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
      emitter.onNext("1");
      emitter.onNext("2");
      emitter.onNext("3");
      emitter.onComplete();
  }

这个 ObservableEmitter 就是我们在上面创建 createEmitter,我们可以看到它的 onNext() 方法中会先判断参数是否为空,为空的话会直接调用 onError() 方法,接着会调用 isDisposed() 方法来判断是否处于 disposed 状态,如果不是的话才会去调用 observer 的 onNext() 方法。也就是示例代码中的:

            @Override
            public void onNext(String s) {
                Log.e("TAG", "onNext():  " + s);
            }

 逻辑有点饶,这里我画了一个流程图大家可以参考一下帮助理解:

至此,基本订阅流程我们就理清楚了。我们从 Observable#subscribe(Observer) 开始,将 Observer 传给 Observable,而 Observable 又会在 onNext(T) 方法中激活 Observer 的 onNext(T) 方法。我们在示例只涉及了少量的 Observable 和 Observer,事实上,我们在 RxJava 中运用的操作符都会在内部创建一个 Observable 和 Observer,虽然在 Observable#subscribeActual(Observer) 中都有自己特定的实现,但是它们大部分都是做两个操作,一是将「下游」传来的 Observer 根据需求进行封装;二就是让「上游」的 Observable subscribe() 该 Observer。

 

三、操作符


现在我们来看一个复杂一点的示例。下面代码的前提是定义了一个 login 接口,返回值为 { isSuccess, UserInfo}。代码如下:

        Observable.create(new ObservableOnSubscribe<LoginApiResult>() {
            @Override
            public void subscribe(ObservableEmitter<LoginApiResult> e) throws Exception {
                e.onNext(login());
            }
        }) //调用登录接口
                .map(new Function<LoginApiBean, UserInfoBean>() {
                    @Override
                    protected UserInfoBean decode(LoginApiBean loginApiBean) {
                        //处理登录结果,返回UserInfo
                        if (loginApiBean.isSuccess()) {
                            return loginApiBean.getUserInfoBean();
                        } else {
                            throw new RequestFailException("获取网络请求失败");
                        }
                    }
                })
                .doOnNext(new Consumer<UserInfoBean>() {    
                    @Override
                    public void accept(@NonNull UserInfoBean bean) throws Exception {
                        //保存登录结果UserInfo
                        saveUserInfo(bean);
                    }
                })
                .subscribeOn(Schedulers.io())   //调度线程
                .observeOn(AndroidSchedulers.mainThread())  //调度线程
                .subscribe(new Consumer<UserInfoBean>() {
                    @Override
                    public void accept(@NonNull UserInfoBean bean) throws Exception {
                        //整个请求成功,根据获取的UserInfo更新对应的View
                        showSuccessView(bean);
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        //请求失败,显示对应的View
                        showFailView();
                    }
                });

首先是任务链的构建,我们先看一下 create() 方法:

    //Observable.java
    public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }

返回 ObservableCreate,继续跟进去看看:

//ObservableCreate.java
public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }
    ...
}

这个类继承了 Observable 类,并存储了我们刚才传进去的 ObservableOnSubscribe 对象。往下,我们调用了 Obserable 的 map() 方法,我们跟进去看一下 map() 方法:

    //Observable.java
    public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
    }

可以看到其实是返回了一个 ObservableMap 对象,接受了两个参数,一个是 this,在这里指的也就是刚才的 ObservableCreate ,还有一个 Function 对象,我们再跟进去看一下 ObservableMap 的基础信息:

//ObservableMap.java
public final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
    final Function<? super T, ? extends U> function;

    public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
        super(source);
        this.function = function;
    }

可以看到其构造方法和刚才的 ObservableCreate 一样,将传入的对象进行了存储。不过可以发现这个类并不是继承自 Observable,而是 AbstractObservableWithUpstream,我们再跟进看看:

//AbstractObservableWithUpstream.java
abstract class AbstractObservableWithUpstream<T, U> extends Observable<U> implements HasUpstreamObservableSource<T> {
    protected final ObservableSource<T> source;

    AbstractObservableWithUpstream(ObservableSource<T> source) {
        this.source = source;
    }

    @Override
    public final ObservableSource<T> source() {
        return source;
    }

}

可以看到这个父类其实继承了 Observable,看到官方的注释可以知道,这个类是所有接受上一级输入的操作符(operator 如 map)的基类,这里的逻辑并不复杂,其实只是简单的封装了一下上一级的输入 source 和输出下一级的数据。分析之后可以看到,调用了 map 方法其实也是返回了一个 Observable 对象。

接着往下是 doOnNext(),看到这里可以猜测也是简单的返回一个 Observable 对象。不管怎么说,先进入源码看一看:

    public final Observable<T> doOnNext(Consumer<? super T> onNext) {
        return doOnEach(onNext, Functions.emptyConsumer(), Functions.EMPTY_ACTION, Functions.EMPTY_ACTION);
    }

    private Observable<T> doOnEach(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
         Action onComplete, Action onAfterTerminate) {
        ObjectHelper.requireNonNull(onNext, "onNext is null");
        ObjectHelper.requireNonNull(onError, "onError is null");
        ObjectHelper.requireNonNull(onComplete, "onComplete is null");
        ObjectHelper.requireNonNull(onAfterTerminate, "onAfterTerminate is null");
        return RxJavaPlugins.onAssembly(new ObservableDoOnEach<T>(this, onNext, onError, onComplete, onAfterTerminate));
    }

可以看到跳转到 doOnEach() 方法,传入的参数除了我们传进来的 Consumer 之外,其它都是传了空实现的 Consumer 对象。可以看到真的是简单的返回一个 Observable 对象。老规矩,先看一下 ObservableDoOnEach 的基础信息:

public final class ObservableDoOnEach<T> extends AbstractObservableWithUpstream<T, T> {
    final Consumer<? super T> onNext;
    final Consumer<? super Throwable> onError;
    final Action onComplete;
    final Action onAfterTerminate;

    public ObservableDoOnEach(ObservableSource<T> source, Consumer<? super T> onNext,
                              Consumer<? super Throwable> onError,
                              Action onComplete,
                              Action onAfterTerminate) {
        super(source);
        this.onNext = onNext;
        this.onError = onError;
        this.onComplete = onComplete;
        this.onAfterTerminate = onAfterTerminate;
    }

同样的对所有信息进行了保存。可以看到这个类也是继承了 AbstractObservableWithUpstream,可以接受上一层的输入,并向下一层输出数据。

接着是线程调度(subscribeOn & observeOn),其实不看也猜得出这里也是直接返回对应的 Observable 对象。首先看一下 subscribeOn() :

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

再看一下 ObserveOn() :

    public final Observable<T> observeOn(Scheduler scheduler) {
        return observeOn(scheduler, false, bufferSize());
    }

    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));
    }

可以看到,这里分别返回了 ObservableSubscribeOn 和 ObservableObserveOn 对象,照旧我们看看这两个类的基础信息:

public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler;

    public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
        super(source);
        this.scheduler = scheduler;
    }

一路看到这里,也能知道他这里的基础信息是什么了吧。再看看另外一个:

public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler;
    final boolean delayError;
    final int bufferSize;
    public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
        super(source);
        this.scheduler = scheduler;
        this.delayError = delayError;
        this.bufferSize = bufferSize;
    }

同样的保存了传进去的基础信息,我们发现其中共同的都保存了 Scheduler 对象,我们先稍微看一下 Scheduler

public abstract class Scheduler {

    @NonNull
    public abstract Worker createWorker();

    @NonNull
    public Disposable scheduleDirect(@NonNull Runnable run) {
        return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
    }

    public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
        final Worker w = createWorker();
        w.schedule(new Runnable() {
            @Override
            public void run() {
                try {
                    run.run();
                } finally {
                    w.dispose();
                }
            }
        }, delay, unit);

        return w;
    }

    public abstract static class Worker implements Disposable {

        @NonNull
        public Disposable schedule(@NonNull Runnable run) {
            return schedule(run, 0L, TimeUnit.NANOSECONDS);
        }

        @NonNull
        public abstract Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit);

}

可以看到,Scheduler 对外暴露了 scheduleDirect() 方法,这个方法通过调用抽象方法 createWorker 得到 worker 对象,然后调用 worker 对象的 schedule() 方法,执行 runnable。看到这里大致就能猜出 Scheduler 对应的逻辑啦,内部的 worker 对象维护自己的线程池,然后每次执行 schedule 方法时把 runnable 对象提交到线程池中。先这样理解,后面我们再深入一下。

接下来终于来到最后这个 subscribe() 方法了,前面全都是直接返回对象,难道所有逻辑都在最后实现吗?进去看一下先:

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {
        return subscribe(onNext, onError, Functions.EMPTY_ACTION, Functions.emptyConsumer());
    }

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
            Action onComplete, Consumer<? super Disposable> onSubscribe) {
        ObjectHelper.requireNonNull(onNext, "onNext is null");
        ObjectHelper.requireNonNull(onError, "onError is null");
        ObjectHelper.requireNonNull(onComplete, "onComplete is null");
        ObjectHelper.requireNonNull(onSubscribe, "onSubscribe is null");

        LambdaObserver<T> ls = new LambdaObserver<T>(onNext, onError, onComplete, onSubscribe);

        subscribe(ls);

        return ls;
    }

    public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
            observer = RxJavaPlugins.onSubscribe(this, observer);

            ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");

            subscribeActual(observer);
        } catch (NullPointerException e) { // NOPMD
            throw e;
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            // can't call onError because no way to know if a Disposable has been set or not
            // can't call onSubscribe because the call might have set a Subscription already
            RxJavaPlugins.onError(e);

            NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
            npe.initCause(e);
            throw npe;
        }
    }

看着比较长,简化后代码是这样的:

public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
         Action onComplete, Consumer<? super Disposable> onSubscribe) {
    LambdaObserver<T> ls = new LambdaObserver<T>(onNext, onError, onComplete, onSubscribe);
    subscribe(ls);
    return ls;
}

public final void subscribe(Observer<? super T> observer) {
    subscribeActual(observer);

因为 subscribe() 的重载方法很多,这里只挑最终的两个,其中 LambdaObserver 其实就是把传进来的 Consumer 包装成一个 Observer,内部就是简单的在各个阶段调用我们传进去的 Consumer 的 accpet() 方法。接着就是直接调用了 subscribeActual() 方法。刚才我们在上述的步骤也说了,这个方法是 Observable 的抽象方法。

其实到这里我们可以看出,整个步骤通过对象的嵌套,形成了一条完整的链:

接着是逆向逐级订阅,按照我们刚才的案例,到最后subscribe() 方法的调用关系应该是这样的:

ObservableObserveOn.subscribe(LambdaObserver)

所以我们跟进看一下 ObservableObserveOn.subscribe() 方法的实现:

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

可以看到,这里通过 Scheduler 创建了一个 worker 对象,然后调用了 source(上一级) 的 subscribe() 方法,并通过已有的observer对象生成一个 ObserveOnObserver(注意是Observer)对象作为传参。看到这里也大概知道套路了,和刚才一样,会一直沿着整条链返回,一个一个订阅对应的 Observable 并生成新的嵌套的 Observer。我们依旧跟着看看,ObservableObserveOn.subscribe() 之后是 ObservableSubscribeOn.subscribe() 

@Override
public void subscribeActual(final Observer<? super T> s) {
    //将上一级传进来的订阅者包装为线程安全的原子变量
    //SubscribeOnObserver只是简单的包装,这里不展开
    final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
    //先在当前线程执行订阅者的onSubscribe方法
    s.onSubscribe(parent);
    //然后在指定的线程中执行source(上一级)的subscribe
    parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
        @Override
        public void run() {
            source.subscribe(parent);
        }
    }));
}

根据我们最开始的业务逻辑,我们这里的 scheduler 应该对应 IO 线程,也就是说往下执行的 subscribe() 操作都是执行在 IO 线程中的。(现在是逆向遍历刚才建立的 observable 链)紧接着 ObservableDoOnEach.subscribe() 

@Override
public void subscribeActual(Observer<? super T> t) {
    source.subscribe(new ObservableDoOnEach.DoOnEachObserver<T>(t, onNext, onError, onComplete, onAfterTerminate));
}

可以看到,这里也是封装了我们传进去的 Consumer 参数,直接调用了上一级的 source.subscribe() 方法。那么就接着往下看。应该来到了 ObservableMap.subscribe() 方法了。

@Override
public void subscribeActual(Observer<? super U> t) {
    source.subscribe(new ObservableMap.MapObserver<T, U>(t, function));
}

可以看到也是封装了我们传进去的 Function 参数,然后调用上一级 source.subscribe() ,也就是 ObservableCreate.subscribe(),也就到了链的一开始。我们跟进看看ObservableCreate.subscribe()

@Override
protected void subscribeActual(Observer<? super T> observer) {
    //首先是创建了CreateEmitter对象,这个类有没有觉得特别眼熟- -
    ObservableCreate.CreateEmitter<T> parent = new ObservableCreate.CreateEmitter<T>(observer);
    //然后调用了订阅者observer的onSubscribe方法
    //这里的订阅者来自刚才的map操作
    observer.onSubscribe(parent);

    try {
        //调用上一级source的subscribe方法
        //显然没有上一级了,这里的source就是我们一开始创建的observer对象,调用的subscribe方法也就是我们调用的login()方法的地方
        source.subscribe(parent);
    } catch (Throwable ex) {
        Exceptions.throwIfFatal(ex);
        //捕获异常
        parent.onError(ex);
    }
}

终于回到了第一级,可以看到一样的封装了 observer 订阅者(这里的订阅者来自 map 操作),然后调用了 source.subscribe() 方法,看到这里不知道你们还记不记得 source 来自哪,看下面代码,这个 source 来自我们一开始调用 Observable.create() 时传进来的参数,而 subscribe() 方法就是我们一开始执行 login() 方法的地方:

Observable.create(new ObservableOnSubscribe<LoginApiResult>() {
            @Override
            public void subscribe(ObservableEmitter<LoginApiResult> e) throws Exception {
                e.onNext(login());
            }
        }) //调用登录接口
        ……省略

也就是说,在刚才所有的逆序遍历过程中,下一级的 Observable 会生成的对应的 Observer 订阅上一级的source

接下来就是激动人心的执行我们定义的任务链了。一趟创建,一趟逆向订阅,我们又回到了最开始的地方。我们刚才分析到,ObservableCreate 会执行我们定义的方法。所以就来到了这段代码:

public void subscribe(ObservableEmitter<LoginApiResult> e) throws Exception {
    e.onNext(login());
}

就是调用 ObservableEmitter.onNext() 方法。我们跟进:

public final class ObservableCreate<T> extends Observable<T> {
    
    protected void subscribeActual(Observer<? super T> observer) {
        //可以看到,这里传入的Observer参数是来自下一级的订阅者
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        //省略一堆- -
    }

    //省略继承关系
    static final class CreateEmitter<T> {
        //保存订阅者
        CreateEmitter(Observer<? super T> observer) {
            this.observer = observer;
        }

        @Override
        public void onNext(T t) {
            //省略判空
            if (!isDisposed()) {
                //调用订阅者的onNext方法
                observer.onNext(t);
            }
         }
    }
}

可以看到吧,简单的执行一些判断后,就调用了订阅者的 onNext() 方法,而通过上面的代码,我们可以看到 observer 来自于 subscribe 时调用构造函数的传参,而通过上述的分析,我们知道这里的订阅者来自下一级,也就是 map 操作生成的订阅者。这里很自然的进入了map操作。(后面不再贴出observer的来源)

我们再往下看到 MapObserver

@Override
public void onNext(T t) {
    //省略一些细节上的判断
    U v;
    //mapper就是我们new 的function对象
    v = mapper.apply(t)
    actual.onNext(v);
}

可以看到,这里调用了我们定义的 apply() 方法,获得了新的对象,然后调用了下一级订阅者的 onNext() 方法。看到这里大概就知道执行任务链的套路了。嵌套的调用下一级的 onNext() 方法。

我们先继续往下看,来到了 DoOnEachObserver 中:

@Override
public void onNext(T t) {
    onNext.accept(t);
    actual.onNext(t);
}

基本上和我们猜想的一样,accept() 方法就是我们定义的 doOnNext() 的操作。

再接着往下来到 SubscribeOnObserver

@Override
public void onNext(T t) {
  actual.onNext(t);
}

这货更直接,直接就调过去了。(这里涉及到Scheduler的线程调度,后面再补充)

快到重点了,再看一下 ObserveOnObserver

@Override
public void onNext(T t) {
    if (sourceMode != QueueDisposable.ASYNC) {
        queue.offer(t);
    }
    schedule();
}

这货逻辑贼复杂,毕竟在这里进行了线程调度。暂时不深入。只需要知道:这货把任务提交给了 Scheduler 中的 worker。等到任务结束获取到结果后会调用下一级的 onNext() 方法。强行来到最后一层了,这里的 Observer 就是我们调用 subscribe 时传入的 Observer 啦。那就是调用:

@Override
public void accept(@NonNull UserInfoBean bean) throws Exception {LoginApiBean
   //整个请求成功,根据获取的UserInfo更新对应的View
   showSuccessView(bean);
}

行了,走完整个流程了。相信看到这里就能大致理解 Rx 的流程怎么走了。在刚才的遍历订阅后,每一步操作都会通知对应的 Observer,从而完成整调任务链。我这个画了一个详细的流程图便于大家理解:

总结一下步骤:

  1. 创建任务链,每一步都会返回对应的Observable对象。
  2. 逆向逐级订阅。每一步都会生成对应的Observer对上一步生成的Observable进行订阅
  3. 执行任务链。执行任务链之后,每一步都会通知对应的Observer,从而完成整调任务链。

 

四、线程切换


.subscribeOn(Schedulers.io())   //调度线程
.observeOn(AndroidSchedulers.mainThread())  //调度线程

我们知道,通过上述这两句代码,就使我们上半部分的请求和保存数据都执行在 io 线程中,而下半部的 ui 更新则执行在主线程。通过这段代码,我们引入几个问题:

  1. observeOn和subscribeOn是如何实现线程调度的?
  2. observeOn和subscribeOn之间是否存在冲突?

首先解决第一个问题,我们先了解一下 ObserveOn() 的实现原理,首先看一下调用:

public final Observable<T> observeOn(Scheduler scheduler) {
    return observeOn(scheduler, false, bufferSize());
}

public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
    return new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize);
}

我们可以看到,ObserveOn() 最终是返回了一个 ObservableObserveOn 对象,并将 scheduler 传入。根据上一章的思路 ObservableObserveOn 会被我们最后 subscribe() 的时候传入的 Observer 订阅。让我们跟进看一下 ObservableObserveOn 被订阅时会执行什么逻辑:

@Override
protected void subscribeActual(Observer<? super T> observer) {
    //TrampolineScheduler 表示当前线程
    if (scheduler instanceof TrampolineScheduler) {
        source.subscribe(observer);
    } else {
        //根据scheduler创建worker
        Scheduler.Worker w = scheduler.createWorker();
        //通过ObservableObserveOnObserver代理
        source.subscribe(new ObservableObserveOn.ObserveOnObserver<T>(observer, w, delayError, bufferSize));
    }
}

这里的逻辑并不难理解,首先是判断了 scheduler 是不是表示当前线程的 TrampolineScheduler,如果是就直接让 observer 订阅上一级的 Observable,也就是跳过当前这一层,即图中的 Observer 直接订阅 ObservableSubscribeOn。然后根据 schedular 生成对应的 worker,并交由 ObserveOnObserver 代理,订阅上一级的 Observable。

根据我们引入的案例,我们以 observeOn(AndroidSchedulers.mainThread())  为例,当完成逆向订阅,执行任务链到ObserveOnObserver 时:

@Override
public void onNext(T t) {
    // 上一级的模式如果不是异步的,加入队列
    if (sourceMode != QueueDisposable.ASYNC) {
        queue.offer(t);
    }
    //进行线程调度
    schedule();
}

void schedule() {
    // 判断当前正在执行的任务数目
    if (getAndIncrement() == 0) {
        worker.schedule(this);
    }
}

首先是判断了 sourceMode,这里先不跟踪这个变量,只需要知道大多数情况下,这个判断是成立,所以会把数据加入队列。然后转而让 worker 执行接下去的步骤。我们跟踪看看,可以发现这是个抽象方法,可以找到他在不同类中有不同实现,分别对应了几种不同的线程调度机制,我们挑选案例中的 AndroidSchedulers.mainThread() 来跟踪。首先我们跟踪 mainThread() 方法,可以发现内部转到了这里:

static final Scheduler DEFAULT
    = new HandlerScheduler(new Handler(Looper.getMainLooper()), false);

我们再跟进 HandlerScheduler,我们知道 worker 是通过 createWorker() 方法产生的:

public Worker createWorker() {
   return new HandlerWorker(handler, async);
}

可以看到直接生成了 HandlerWorker,并传入了一开始创建的绑定了 MainLooper 的 Handler。看到这里也能大致猜出,后续会把任务传给这个 handler 执行:

@Override
public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
    //省略部分代码
    ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);

    Message message = Message.obtain(handler, scheduled);
    message.obj = this; // Used as token for batch disposal of this worker's runnables.

    handler.sendMessageDelayed(message, Math.max(0L, unit.toMillis(delay)));

    return scheduled;
}

可以看到这里将传进来的 runnable 包装成 ScheduledRunnable,然后提交给绑定的 handler。我们知道,后续 Handler 会调用 ScheduledRunnable 的 run() 方法:

ScheduledRunnable(Handler handler, Runnable delegate) {
    this.handler = handler;
    this.delegate = delegate;
}

@Override
public void run() {
    try {
        delegate.run();
    } catch (Throwable t) {
        //……
    }
}

可以看到,只是简单的调用了我们传入的 runnable 的 run() 方法,也就是刚才我们在 ObserveOnObserver 中通过 schedule() 方法传入的 runnable,我们回去看看:

void schedule() {
    // 判断当前正在执行的任务数目
    if (getAndIncrement() == 0) {
        worker.schedule(this);
    }
}

可以看到其实本身就是个 runnable,我们看一下 ObserveOnObserver 的 run() 方法:

@Override
public void run() {
    //输出结果是否融合
    if (outputFused) {
        drainFused();
    } else {
        drainNormal();
    }
}

可以看到,根据 outputFused 来跳转方法,这里先不跟踪这个变量,后面会再提到。现在只需要知道当连续两个 observable 都需要线程调度时(比如从 observeOn 到 observeOn ),这个 outputFused 才会发生变化,默认为 false。那么这里,我们先进入 drainNormal() 方法:

void drainNormal() {
    int missed = 1;
    final SimpleQueue<T> q = queue;
    final Observer<? super T> a = actual;
    //第一层循环
    for (;;) {
        // 检查异常处理
        if (checkTerminated(done, q.isEmpty(), a)) {
            return;
        }
        //第二层循环
        for (;;) {
            boolean d = done;
            T v;
            //从队列中获取数据
            v = q.poll();
            boolean empty = v == null;
            // 检查异常
            if (checkTerminated(d, empty, a)) {
                return;
            }
            //如果没有数据了,跳出
            if (empty) {
                break;
            }
            //执行下一次操作。
            a.onNext(v);
        }
        //减掉执行的次数,并获取剩余任务数量,然后再次循环
        //直到获取剩余任务量为0,跳出循环
        missed = addAndGet(-missed);
        if (missed == 0) {
            break;
        }
    }
}

这里的逻辑其实也不难,具体可以看注释。到这里其实已经切换了线程,然后就是分发数据,逐个调用onNext() 操作了。直到没有数据就跳出循环。(总觉得这里missed的设计很奇怪- -为什么是初始化1而不是missed=get()呢。望有大神解答~)

看到这里也就大致明白了 ObserveOn() 的流程了。总结一下:ObserveOn 会用一个 queue 保存上一级传下来的数据,然后通过 scheduler 创建一个 worker,提交数据,并将任务执行在 worker 设置的线程中。

看完 ObserveOn,我们看一下 subscribeOn(),首先看一下当它被订阅时会执行什么操作:

//ObservableSubscribeOn.java
@Override
public void subscribeActual(final Observer<? super T> s) {
    //创建对应的Observer
    final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
    //执行线程调度,内部会订阅上一级的Observable
    parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}

可以看到这里直接进行了线程调度,创建了 SubscribeTask 任务,然后交由 Scheduler 执行。我们先看看 scheduleDirect() 会执行什么操作:

@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    final Scheduler.Worker w = createWorker();

    Scheduler.DisposeTask task = new Scheduler.DisposeTask(run, w);

    w.schedule(task, delay, unit);

    return task;
}

可以看到这里和我们刚才追踪 ObserveOn() 时的逻辑一样,都是将任务交给了 Worker 处理。我们刚才已经分析了,Worker 会将任务提交给对应的线程执行。所以我们回过头看一下我们提交了什么任务:

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

可以看出,这里将订阅的操作提交给了 Worker 执行。总结一下:subscribeOn() 会将订阅上一级的操作调交给 worker 中对应的线程执行。

总结

我们还是以上述引入的例子为例,可以看出,整个过程进行了两次线程调度,首先是 subscribeOn(),然后是ObserveOn(),这个过程比较简单,先解析这个过程。根据上一篇文章的分析,RxJava的整个流程分为三个步骤:

  1. 创建任务链,这里没有涉及线程调度。默认执行在当前线程,在这里也就是主线程
  2. 逆向订阅,这里当遇到 ObserveOn() 的时候,ObserveOn() 直接进行了订阅操作,所以没有影响。但是但我们订阅 ObservableSubscribeOn 的时候,其便将订阅操作提交到了对应线程,所以后续的订阅操作都执行在对应线程,在这里便是 IO 线程
  3. 执行任务链,受到 ObservableSubscribeOn 的影响,这里也会继续执行在 IO 线程。但是当我们执行到 ObserveOnObserver 的时候,onNext() 操作会执行在对应的线程中,在这里也就是切换到主线程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值