Rxjava2你应该懂的源码,其实并不难(二)

接上篇继续。

一、线程切换observeOn

Observable.just("1")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer)

我们知道,当调用observeOn之后,后面执行的代码都将切换到他指定的线程,除非再次调用observeOn切换其他线程。上源码:

@CheckReturnValue
    @SchedulerSupport(SchedulerSupport.CUSTOM)
    public final Observable observeOn(Scheduler scheduler) {
        return observeOn(scheduler, false, bufferSize());
    }

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

经过第一篇的分析,套路已经很熟悉了。最终就是new了一个ObservableObserveOn并返回,而这个ObservableObserveOn估计也是Observable的子类。进去看一下。

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

abstract class AbstractObservableWithUpstream extends Observable implements HasUpstreamObservableSource {

    /** The source consumable Observable. */
    protected final ObservableSource source;

    /**
     * Constructs the ObservableSource with the given consumable.
     * @param source the consumable Observable
     */
    AbstractObservableWithUpstream(ObservableSource source) {
        this.source = source;
    }

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

}

果然不出所料。这样就简单了,我们只要分析他的实现方法subscribeActual就可以了。

@Override
    protected void subscribeActual(Observer observer) {
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
            Scheduler.Worker w = scheduler.createWorker();

            source.subscribe(new ObserveOnObserver(observer, w, delayError, bufferSize));
        }
    }

createWorker方法,具体实现在我们传入的Scheduler:

final class HandlerScheduler extends Scheduler {
    private final Handler handler;

    HandlerScheduler(Handler handler) {
        this.handler = handler;
    }

@Override
    public Worker createWorker() {
        return new HandlerWorker(handler);
    }
}

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

private static final class HandlerWorker extends Worker {
        private final Handler handler;

        private volatile boolean disposed;

        HandlerWorker(Handler handler) {
            this.handler = handler;
        }

        @Override
        public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
            if (run == null) throw new NullPointerException("run == null");
            if (unit == null) throw new NullPointerException("unit == null");

            if (disposed) {
                return Disposables.disposed();
            }

            run = RxJavaPlugins.onSchedule(run);

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

            // Re-check disposed state for removing in case we were racing a call to dispose().
            if (disposed) {
                handler.removeCallbacks(scheduled);
                return Disposables.disposed();
            }

            return scheduled;
        }

        @Override
        public void dispose() {
            disposed = true;
            handler.removeCallbacksAndMessages(this /* token */);
        }

        @Override
        public boolean isDisposed() {
            return disposed;
        }
    }

代码有点多,一点点分析。创建的worker叫HandlerWorker。他有个schedule方法,是执行runnable的。再看这句是重点:

Message message = Message.obtain(handler, scheduled);

把scheduled作为一个runnable发到消息队列中,通过looper循环以后交给handler去处理。而这里的handler对应的looper是主线程的,所以runnable的代码就运行在主线程。最终完成了线程的切换(切换到主线程)。不是很熟悉handler代码的同学,我在这里贴下代码吧:

/**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

private static void handleCallback(Message message) {
        message.callback.run();
    }

msg.callback就是我们之前创建messge对象的时候传入的scheduled,也就是一个runnable,然后去执行他的run方法。
再回过来,那么scheduled到底是个什么呢?

private static final class ScheduledRunnable implements Runnable, Disposable {
        private final Handler handler;
        private final Runnable delegate;

        private volatile boolean disposed;

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

        @Override
        public void run() {
            try {
                delegate.run();
            } catch (Throwable t) {
                IllegalStateException ie =
                    new IllegalStateException("Fatal Exception thrown on Scheduler.", t);
                RxJavaPlugins.onError(ie);
                Thread thread = Thread.currentThread();
                thread.getUncaughtExceptionHandler().uncaughtException(thread, ie);
            }
        }
}

其实只是runnable的包装类,如果你的代码出了异常,这里做了处理。
好了,我们回顾一下之前的思路。我们为了看createWorker方法的具体实现进来,发现创建的是HandlerWorker,而HandlerWorker里面有个schedule方法,他的作用是把传入的runnable参数包装成ScheduledRunnable以后,通过handler让他运行在主线程,完成线程的切换。ok,问题已经变得简单了,我们只要找到哪里调用了schedule方法,就完全明白了。
回到ObservableObserveOn#subscribeActual,我们最初的地方

@Override
    protected void subscribeActual(Observer observer) {
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
            Scheduler.Worker w = scheduler.createWorker();

            source.subscribe(new ObserveOnObserver(observer, w, delayError, bufferSize));
        }
    }

第一步创建worker以后,然后调用了source的subscribe方法。source我们上篇分析过,他是创建当前Observable的Observable,那么ObserveOnObserver又是什么呢?

static final class ObserveOnObserver extends BasicIntQueueDisposable
    implements Observer, Runnable {

ObserveOnObserver(Observer actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
            this.actual = actual;
            this.worker = worker;
            this.delayError = delayError;
            this.bufferSize = bufferSize;
        }

@Override
        public void onNext(T t) {
            if (done) {
                return;
            }

            if (sourceMode != QueueDisposable.ASYNC) {
                queue.offer(t);
            }
            schedule();
        }

void schedule() {
            if (getAndIncrement() == 0) {
                worker.schedule(this);
            }
        }
}

看到没,他就是个Observer的封装类,持有我们传入的observer的引用。装饰者模式真是无处不在啊。以onNext为例,又会去调用schedule()。bingo,这里面正是调用了worker的sechedule方法。终于对上了。执行的runnable是this,那么看下他的run方法:

@Override
        public void run() {
            if (outputFused) {
                drainFused();
            } else {
                drainNormal();
            }
        }

void drainNormal() {
            int missed = 1;

            final SimpleQueue q = queue;
            final Observer a = actual;

            for (;;) {
                if (checkTerminated(done, q.isEmpty(), a)) {
                    return;
                }

                for (;;) {
                    boolean d = done;
                    T v;

                    try {
                        v = q.poll();
                    } catch (Throwable ex) {
                        Exceptions.throwIfFatal(ex);
                        s.dispose();
                        q.clear();
                        a.onError(ex);
                        worker.dispose();
                        return;
                    }
                    boolean empty = v == null;

                    if (checkTerminated(d, empty, a)) {
                        return;
                    }

                    if (empty) {
                        break;
                    }

                    a.onNext(v);
                }

                missed = addAndGet(-missed);
                if (missed == 0) {
                    break;
                }
            }
        }

最终调用了我们自己的observer#onNext

我再重新梳理一遍:

@Override
    protected void subscribeActual(Observer observer) {
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
            Scheduler.Worker w = scheduler.createWorker();

            source.subscribe(new ObserveOnObserver(observer, w, delayError, bufferSize));
        }
    }

先是创建一个worker,然后通过source#subscribe间接调用了worker#schedule,让runnable执行在主线程。而这个runnable又持有了observer,会调用observer的onNext等方法。
从这里我们也发现了,我们自己的observer执行的onNext,实际上是被锁死在了observeOn指定的线程了(前提是要调用observeOn方法)。

二、关于线程切换你必须要知道的一些事

在说知道的事之前,我们先来分析下代码,这有助于同学们理解我想说的事。

Observable.just("1")  //1号
                .observeOn(Schedulers.io())   //2号
                .subscribeOn(Schedulers.io())   //3号
                .subscribeOn(AndroidSchedulers.mainThread())  //4号
                .observeOn(AndroidSchedulers.mainThread())  //5号
                .map { 
                    return@map it.plus("2")
                }  //6号
                .observeOn(Schedulers.io())  //7号
                .subscribe(observer)

这里我为了分析的需要,故意来回切换线程。看注释,通过之前的分析,我们知道实际上每一行都生成了一个Observable的子类,为了方便区分,我后面就用1号,2号来称呼。
我们来捋一捋,注意,接下来的内容一定要弄懂!
1号是事件源,1号创建了2号然后把自己传给2号,2号创建了3号把自己传给3号,3号创建了4号把自己传给4号,4号创建了5号把自己传给5号,5号创建了6号把自己传给6号,6号创建了7号把自己传给7号。而每个Obsersable里面都对应一个observer。 最终7号Obsersable调用subscribe,把我们的observer传进来(后面我都称呼为原始observer)。这时候,会去调用7号的subscribeActual,具体实现是用7号observer装饰原始observer,再去调用之前传进去的6号的subscribeActual方法,6号的subscribeActual方法具体实现又是用6号的observer装饰7号装饰过的observer,再去调用之前传进去的5号的subscribeActual方法。以此类推,最终调用1号的subscribeActual,并把经过层层装饰的observer传进去。1号是事件源,我们在第一篇已经分析过,他的subscribeActual最终会去调用传进来的observer的onNext方法,实际会去调用2号装饰过的observer#onNext,2号装饰过的observer因为装饰了3号的observer,又会去调用3号observer装饰过的observer,以此类推,最终会调用原始observer(也就是我们自己的observer)。
像不像套娃娃,observable创建的时候是从1号开始套到7号,执行的时候是从7号执行到1号;而observer恰好相反,创建的时候从原始observer开始套到1号,执行的时候从1号到原始observer。

好了,现在开始说关于线程切换你需要知道的事!

1、subscribeOn只有第一次设置是有效的

通过上面的分析,我们知道observable#subscribeActual执行顺序是从7到1,那么无论之后调用了几次subscribeOn,执行到后面肯定要经过第一次的subscribeOn,在图中就是2号。2号是运行在线程池,所以之后的执行1号也就在线程池。这就好比管你们之前怎么折腾,老子在终点等你们。

2、observeOn设置多次都是有效的,并且每设置一次后面的代码就会切换到相应的线程。

通过上面的分析,我们知道observer#onNext执行顺序是从1到原始observer。那么2号对应的observer#onNext就执行在线程池,接下来5号又把线程切换到了主线程,那么6号对应的observer#onNext就执行在主线程,7号又把对应的observer#onNext带到了线程池,所以最终原observer#onNext执行在线程池。

说些题外话

Scheduler实际就相当于java的executor,Ioscheduler、MainScheduler就相当于线程池,Schedulers就相当于Executors。为什么是这样这里就不说了,请同学们自己看源码理解吧。

其实Rxjava2还有几十个操作符,如果一个个分析需要太多篇文章也没有必要。套路是差不多的,都是创建observable的子类,有兴趣的同学自己去触类旁通吧。如果有写得不正确的欢迎指正,也欢迎留言探讨。

你可能感兴趣的:(Rxjava2你应该懂的源码,其实并不难(二))