08.RxJava运作流程源码分析

RxJava线程切换非常方便,只要调用subscribeOn(Schedules.io())就可以使前边的操作运行于子线程,调用obsersableOn(AndroidSchedules.mainThread())就可以设置后边的代码运行于主线程,那么是如此神奇,他是如何实现的?

今天就以下边的代码为切入点深入源码看一下

Observable.just("我是网络图片url").map(new Function() {
            @Override
            public String apply(@NonNull String s) throws Exception {
                Log.i(TAG, "apply1 thread:"+Thread.currentThread().getName());
                Log.i(TAG, "apply1");
                s = s +" 加上一个时间戳后";
                return s;
            }
        }).map(new Function() {
            @Override
            public String apply(@NonNull String s) throws Exception {
                Log.i(TAG, "apply2 thread:"+Thread.currentThread().getName());
                Log.i(TAG, "apply2");
                s = s +" 加上第二个参数后";
                return s;
            }
        }).subscribeOn(Schedulers.io()).subscribe(new Observer() {
            @Override
            public void onSubscribe() {
                Log.i(TAG, "onSubscribe thread:"+Thread.currentThread().getName());
                Log.i(TAG, "onSubscribe");
            }

            @Override
            public void onNext(@NonNull String s) {
                Log.i(TAG, "onNext thread:"+Thread.currentThread().getName());
                Log.i(TAG, "onNext:"+s+" 开启下载这个图片");

            }

            @Override
            public void onError(@NonNull Throwable throwable) {
                Log.i(TAG, "onError");
                throwable.printStackTrace();
            }

            @Override
            public void onComplete() {
                Log.i(TAG, "onComplete thread:"+Thread.currentThread().getName());
                Log.i(TAG, "onComplete:下载完成");
            }
        });

程序运行流程图如下


08.RxJava运作流程源码分析_第1张图片
RxJava运行流程图.png

just方法

创建一个ObservableJust对象返回,并将just传入的参数保保存为value

@CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public static  Observable just(T item) {
        ObjectHelper.requireNonNull(item, "The item is null");
        return RxJavaPlugins.onAssembly(new ObservableJust(item));
    }

@SuppressWarnings({ "rawtypes", "unchecked" })
    @NonNull
    public static  Observable onAssembly(@NonNull Observable source) {
        Function f = onObservableAssembly;
        if (f != null) {
            return apply(f, source);
        }
        return source;
    }

map方法

同样道理,创建一个ObservableMap对象,由于map方法由上边的ObservableJust对象调用,所以构造方法中传入的this表示的就是ObservableJust对象,创建ObservableMap对象后,保存上一级产生的ObservableJust为当前ObservableMap对象中的成员变量source,保存当前function回调接口,这样一来,当前对象持有上一级ObservableJust的引用。不管map调用几次,当前对象都会持有上一级产生的对象的引用

@CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final  Observable map(Function mapper) {
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        return RxJavaPlugins.onAssembly(new ObservableMap(this, mapper));
    }

假设再次调用map之后,这个map就是由上一次调用map产生的ObservableMap对象调用的,此时会将上一级这个ObservableMap对象保存到当前对象的source成员变量中,就这样,一级套一级

subscribeOn方法

产生一个ObservableSubscribeOn对象,并将上一级的ObservableMap对象保存为当前对象的source变量,保存传入的scheduler,那么这个scheduler是什么?

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

subscribeOn(Schedulers.io())方法使上边的操作在子线程中执行,Schedulers.io()就是上边传入的schedulers,我们看一下schedulers是如何创建的
来到Schedulers类中

public static Scheduler io() {
        return RxJavaPlugins.onIoScheduler(IO);
    }

可以找到IO对象是在本类静态代码块中创建的

 static {
        ....
        IO = RxJavaPlugins.initIoScheduler(new IOTask());
        ....
    }

IOTask是一个实现了Callable接口的线程

static final class IOTask implements Callable {
        @Override
        public Scheduler call() throws Exception {
            return IoHolder.DEFAULT;
        }
    }

线程执行会得到Scheduler,可以看到,这是以内部类形式实现的单例模式

static final class IoHolder {
        static final Scheduler DEFAULT = new IoScheduler();
    }

可以看到,这个IoScheduler内部是线程池实现的

CachedWorkerPool update = new CachedWorkerPool(KEEP_ALIVE_TIME, KEEP_ALIVE_UNIT, threadFactory);

也就是说,当我们在代码中设置了这个操作之后(subscribeOn(Schedulers.io())),会创建一个线程池(如果存在就不必创建),很明显,最终将会需要放在子线程中执行的方法在这个线程池中执行,从而达到切换线程的效果,目前看到这里,这只能作为一个猜想,我们继续往下看

observeOn(AndroidSchedulers.mainThread())方法

这个方法执行会保存一个运行于主线程的Scheduler,这个主线程Scheduler如何创建的?
AndroidSchedulers中

private static final class MainHolder {

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

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

    /** A {@link Scheduler} which executes actions on the Android main thread. */
    public static Scheduler mainThread() {
        return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);

可以看到这个Scheduler是通过封装Handler得到的一个运行于主线程的封装类,这里将它保存起来。最后我们看subscribe方法

subscribe方法

public final void subscribe(Observer observer) {
        ......
            subscribeActual(observer);
        ......
    }

protected abstract void subscribeActual(Observer observer);

由于subscribeActual方法是抽象的,那么要从其子类中找,subscribe方法由上次操作observeOn方法得到的ObservableObserveOn对象调用,所以会执行这个类中的subscribeActual方法,进入ObservableObserveOn中

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

scheduler就是之前保存的AndroidSchedulers.mainThread对象,这里的source表示的就是上一级产生的Observable对象,具体到当前代码,就是ObservableSubscribeOn,调用ObservableSubscribeOn中的subscribe方法,逐层向上传递,直到传递到ObservableJust对象中,再不断的调用map中传入的function回调方法apply,当apply方法调用完成,再执行Observer的onNext onComplete方法,具体流程见上边的流程图,下一篇博客我将会详细分析线程调度的源码。
到这里,这段示例代码的流程已经走了一遍

写了一个简化版的RxJava,实现了just map subscribeOn obserseOn方法,有助于对原理的理解,GitHub地址:https://github.com/renzhenming/MyRxJava

你可能感兴趣的:(08.RxJava运作流程源码分析)