RxJava2核心源码解析

RxJava2源码解析

一、简介

RxJava是一款基于事件流的链式调用,支持切换线程,使用简单。

接下来,会根据RxJava2版本进行分析。本文不会讲具体详细的操作符使用,主要从下面几个问题去看待源码是如何设计实现的

  • 怎么做到响应事件发射源发出的消息
  • 如何通过简单操作符达到切换线程的
  • 为什么发射源只支持第一次线程切换,而订阅者可以多次切换线程

先对下文的一些名词做说明:

  • 发射源 = 被观察者
  • 订阅者 = 观察者

二、从代码看设计

1、核心设计–观察者模式

先从简单的实现来看

//创建发射源(被观察者)
Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                emitter.onComplete();
            }
        })
        //切换发射源线程
        .subscribeOn(Schedulers.io())
        //切换订阅者线程
        .observeOn(AndroidSchedulers.mainThread())
        //订阅消息(观察者)
        .subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Integer integer) {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

从链式调用上,我们看起来像是Observable订阅了Observer,实际上我们需要返过来看,是Observable被Observer订阅。接下来我们先从订阅方法分析

public abstract class Observable<T> implements ObservableSource<T> {
    @SchedulerSupport(SchedulerSupport.NONE)
    @Override
    public final void subscribe(Observer<? super T> observer) {
        //校验空
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
            //hook类
            observer = RxJavaPlugins.onSubscribe(this, observer);

            ObjectHelper.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null Observer. Please change the handler provided to RxJavaPlugins.setOnObservableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");
            //执行实际的订阅处理,该方法为抽象方法,需要到达订阅者之前的所有操作类实现重写。传入观察者,需要前序流程根据实际通知观察者
            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;
        }
    }

    //抽象方法,需要到达订阅者之前的所有操作类实现重写
    protected abstract void subscribeActual(Observer<? super T> observer);
}

接下来,我们先忽略中间的线程切换符号,来看一看发射源的实现

public abstract class Observable<T> implements ObservableSource<T> {
    @CheckReturnValue
    @NonNull
    @SchedulerSupport(SchedulerSupport.NONE)
    public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
        //判空
        ObjectHelper.requireNonNull(source, "source is null");
        //将接口包装成ObservableCreate,而ObservableCreate是Observable的子类
        return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }
}


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);
        //首先通知观察者Dispose对象,CreateEmitter实现了Disposable接口,外部可以通过dispose()方法来取消发射器发射数据,内部DisposableHelper.setOnce保证只调用一次
        observer.onSubscribe(parent);

        try {
            //将发射器交给发射源接口发送数据,需外部手动实现,例如上面离职create里的subscribe方法里的onNext()等
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }

    //静态内部类发射器
    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;
            }
            //如果没有调用dispose取消发送,则通知观察者
            if (!isDisposed()) {
                observer.onNext(t);
            }
        }

        @Override
        public void onError(Throwable t) {
            //先尝试发送错误信息,未发送者hook处理
            if (!tryOnError(t)) {
                RxJavaPlugins.onError(t);
            }
        }

        @Override
        public boolean tryOnError(Throwable t) {
            //error不能为空
            if (t == null) {
                t = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources.");
            }
             //如果没有调用dispose取消发送,则通知观察者
            if (!isDisposed()) {
                //通知错误之后,取消发送,这就是为什么错误回调之后,会停止发送的原因
                try {
                    observer.onError(t);
                } finally {
                    dispose();
                }
                return true;
            }
            return false;
        }

        @Override
        public void onComplete() {
            if (!isDisposed()) {
                //通知完成之后,取消发送,这就是为什么完成回调之后,会停止发送的原因
                try {
                    observer.onComplete();
                } finally {
                    dispose();
                }
            }
        }

        @Override
        public void setDisposable(Disposable d) {
            //dispose帮助类,传入原子索引类来控制
            DisposableHelper.set(this, d);
        }

        @Override
        public void setCancellable(Cancellable c) {
            setDisposable(new CancellableDisposable(c));
        }

        @Override
        public ObservableEmitter<T> serialize() {
            return new SerializedEmitter<T>(this);
        }

        @Override
        public void dispose() {
            DisposableHelper.dispose(this);
        }

        @Override
        public boolean isDisposed() {
            return DisposableHelper.isDisposed(get());
        }
        ······
    }

    ······
}


至此我们明白了RxJava源码是根据观察者模式主线来实现的。
同时能回答我们提出的第一个问题:

  • 怎么做到响应事件发射源发出的消息

通过调用subscribe方法,再实际调用subscribeActual(obserser)将观察者对象传给被观察者,这样被观察者有变动就能通知到观察者

2、锦上添花–装饰者模式

为了弄懂线程切换原理,我们以装饰者模式的角度,更易理解是怎么样切换的

2.1 发射源切换线程

先从发射源先从切换分析subscribeOn

public abstract class Observable<T> implements ObservableSource<T> {
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.CUSTOM)
    public final Observable<T> subscribeOn(Scheduler scheduler) {
        //校验空
        ObjectHelper.requireNonNull(scheduler, "scheduler is null");
        //构建ObservableSubscribeOn对象,并传入发射源和线程调度器
        return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
    }

}


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

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


    @Override
    public void subscribeActual(final Observer<? super T> observer) {
        //传入观察者,包装成Dispose对象
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(observer);

        //通知观察者onSubscribe
        observer.onSubscribe(parent);

        //设置Disposable,并设置发射器,对应的线程调度器scheduler执行scheduleDirect方法传入Runnable接口对象来运行
        parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
    }//前面有讲到,这个方法是到达观察者之前都要实现的,实际订阅执行的地方
    

    //内部类,实现了Runnable接口
    final class SubscribeTask implements Runnable {
        private final SubscribeOnObserver<T> parent;

        SubscribeTask(SubscribeOnObserver<T> parent) {
            this.parent = parent;
        }

        @Override
        public void run() {
            //在run方法中观察者订阅被观察者,该方法运行到哪个线程就会在哪个线程发送数据
            //同时也会影响观察者的调用线程
            source.subscribe(parent);
        }
    }
    ······
}

public abstract class Scheduler {
    @NonNull
    public Disposable scheduleDirect(@NonNull Runnable run) {
        //会在调用三个参数的方法
        return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
    }

    //默认实现是当前线程
     @NonNull
    public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
        //创建工作者,抽象方法
        final Worker w = createWorker();
        //hook调用
        final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
        //默认Run方法,运行在当前线程
        DisposeTask task = new DisposeTask(decoratedRun, w);
        //在对应线程执行任务
        w.schedule(task, delay, unit);

        return task;
    }

}

下面就以AndroidSchedulers.mainThread()来做分析

public final class AndroidSchedulers {

    private static final class MainHolder {
        //构造出默认的主线程Handler来切换线程
        static final Scheduler DEFAULT
            = new HandlerScheduler(new Handler(Looper.getMainLooper()), false);
    }

    private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
            new Callable<Scheduler>() {
                @Override public Scheduler call() throws Exception {
                    return MainHolder.DEFAULT;
                }
            });

    /** 获取一个主线程执行动作的Scheduler */
    public static Scheduler mainThread() {
        //获取MAIN_THREAD,实际处理是HandlerScheduler
        return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
    }
}




final class HandlerScheduler extends Scheduler {
    private final Handler handler;
    private final boolean async;

    HandlerScheduler(Handler handler, boolean async) {
        this.handler = handler;
        this.async = async;
    }

    @Override
    @SuppressLint("NewApi") 
    //直接订阅执行的地方
    public Disposable scheduleDirect(Runnable run, long delay, TimeUnit unit) {
        if (run == null) throw new NullPointerException("run == null");
        if (unit == null) throw new NullPointerException("unit == null");
        //hook方法run先处理
        run = RxJavaPlugins.onSchedule(run);
        //包装成ScheduledRunnable对象
        ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);
        //async默认为false,构建非异步消息并延迟发视频发送。之后Message就会在主线程调用run()方法处理消息内容
        Message message = Message.obtain(handler, scheduled);
        if (async) {
            message.setAsynchronous(true);
        }
        handler.sendMessageDelayed(message, unit.toMillis(delay));
        return scheduled;
    }


}


/**
  *  回到SubscribeTask类,就会执行该类的run()方法,发射源就在这里运行
  **/
final class SubscribeTask implements Runnable {
        private final SubscribeOnObserver<T> parent;

        SubscribeTask(SubscribeOnObserver<T> parent) {
            this.parent = parent;
        }

        @Override
        public void run() {
            //再run方法中观察者订阅被观察者,该方法运行到哪个线程就会在哪个线程发送数据
            source.subscribe(parent);
        }
    }

那我们深入想一想,假如有多个subscribeOn

run()方法里的source是同一个,按照链式调用顺序,包装类是跟链式调用时相反方向的,意思就是会先调用最后一个设置的subscribeOn的方法,这个时候发射源没有发射数据,在调用包装之前的subscribeOn,层层朝内层包装调用,最后达到切换线程的就是第一个subscribeOn设置的run()方法里。

如下图
在这里插入图片描述

2.2 订阅者切换线程

我们从ObserverOn开始看

public abstract class Observable<T> implements ObservableSource<T> {
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.CUSTOM)
    public final Observable<T> observeOn(Scheduler scheduler) {
        //调用三个参数方法,默认不延时发送错误
        return observeOn(scheduler, false, bufferSize());
    }

    @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");
        //构建ObservableObserveOn对象并传入发射源和线程调度器等
        return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
    }
}



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

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        //如果在默认当前线程工作,直接订阅
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
            //创建线程调度对应的工作者
            Scheduler.Worker w = scheduler.createWorker();
            //在当前线程或者第一个subscribeOn指定的线程订阅,构建ObserveOnObserver(内部类)对象传入工作者和观察者,一遍在指定线程通知观察者
            //从这里已经能说明,当前的subscribeOn影响的是之后的一个订阅事件
            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
        }
    }

    static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
    implements Observer<T>, Runnable {
        ······
        private static final long serialVersionUID = 6576896619930983584L;

        ObserveOnObserver(Observer<? super T> actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
            this.downstream = 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();
        }

        @Override
        public void onError(Throwable t) {
             //已经结束发送直接返回
            if (done) {
                RxJavaPlugins.onError(t);
                return;
            }
            error = t;
            //出错,设置已完成,不再发送
            done = true;
            //对应线程执行
            schedule();
        }

        @Override
        public void onComplete() {
             //已经结束发送直接返回
            if (done) {
                return;
            }
            //结束,设置已完成,不再发送
            done = true;
            //对应线程执行
            schedule();
        }

        //实际执行的方法
        void schedule() {
            if (getAndIncrement() == 0) {
                //线程调度对应的工作者在自己线程执行run()回调,下方依然以主线程来举例
                worker.schedule(this);
            }
        }

        @Override
        public void run() {
            //实际开始执行回调方法,根据不同情况执行onNext、onError、onComplete等回调
            //这里不继续查看详细判断,与这次主题关联就不大
            if (outputFused) {
                drainFused();
            } else {
                drainNormal();
            }
        }

    }
    ······
}

接下来看,mainThread是怎么达到切换线程的目的的

//Scheduler#Worker
//这个是调度器对应的执行工作者,需要子类自己去实现创建,和具体执行事情的方法
public abstract class Scheduler {
    @NonNull
    public abstract Worker createWorker();

    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对应的是HandlerScheduler
final class HandlerScheduler extends Scheduler {
     @Override
    public Worker createWorker() {
        //创建主线程handler工作者
        return new HandlerWorker(handler, async);
    }
    
    private static final class HandlerWorker extends Worker {
        private final Handler handler;
        private final boolean async;

        private volatile boolean disposed;

        HandlerWorker(Handler handler, boolean async) {
            this.handler = handler;
            this.async = async;
        }

        @Override
        @SuppressLint("NewApi") 
        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");
            //如果已经dispose,则取消
            if (disposed) {
                return Disposables.disposed();
            }
            //hook调用
            run = RxJavaPlugins.onSchedule(run);

            //包装成ScheduledRunnable对象
            ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);
            //发送消息,等待消息队列取出执行scheduled的run()方法,由于上一节说过handler是主线程的handler,所以run()方法在线程执行,就达到了切换的效果
            Message message = Message.obtain(handler, scheduled);
            message.obj = this; // Used as token for batch disposal of this worker's runnables.

            if (async) {
                message.setAsynchronous(true);
            }

            handler.sendMessageDelayed(message, unit.toMillis(delay));

            // 重新检查已处置状态以将其删除,以防万一我们正在争夺对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;
        }
    }
}

至此,能明白观察者是怎么切换线程来回调,接下来分析为什么观察者可以多次切换线程

上面再ObservableObserveOn的subscribeActual方法中以及之后的分析,能判断出,下方的订阅事件只受最近的一次observeOn影响(即使调用多次observeOn)。由于中途可能存在map、filter、flatMap等转换,这些均会受调用它之前设置的observeOn线程影响。所以observeOn可以多次生效,但是连续调用,也只有转换或订阅之前最近一次的生效。

如下图
在这里插入图片描述

上面的第二、三问题也能够回答了

  • 如何通过简单操作符达到切换线程的
    通过包装类,将source发送源和observer订阅者通过线程调度器包装一次,来达到切换的效果

  • 为什么发射源只支持第一次线程切换,而订阅者可以多次切换线程
    通过多次包装类,发射源只有包装的最里层的线程切换是实际运行的线程。
    订阅者可以通过层层包装转换,切换线程,影响之后的转换或者订阅的线程。所以只要不是连续调用,就会有多次切换生效。但是如果是连续调用,则处理消息之前最近的一次生效

总结

这里仅仅分析了核心的设计,未涉及到具体操作符的执行,也未涉及到具体元数据的发送流情况,如果感兴趣,读者可以自行查看。我将在有时间时补充这部分。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值