Rxjava从使用到原码的解析十三: Rxjava线程切换源码分析(终结版)

先来一段标准代码分析

        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                Log.e(TAG, "上游线程: " + Thread.currentThread().getName());
                e.onNext("1111");
            }
        }).map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) throws Exception {
                return 404;
            }
            //给上游分配多次,只会在第一次切换
        }).subscribeOn(Schedulers.io())
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.e(TAG, "onSubscribe: " + Thread.currentThread().getName());

                    }

                    @Override
                    public void onNext(Integer s) {
                        Log.e(TAG, "下游线程: " + Thread.currentThread().getName());

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

 

当执行.subscribeOn(Schedulers.io())的时候,这个是切换上游线程的方法

先来看一下Schedulers.io()里面是什么,从字面意思上看肯定是一个io线程,

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

    public static Scheduler onIoScheduler(@NonNull Scheduler defaultScheduler) {
        Function<? super Scheduler, ? extends Scheduler> f = onIoHandler;
        if (f == null) {
            return defaultScheduler;
        }
        return apply(f, defaultScheduler);
    }

上面二个方法返回的是一个Scheduler类,这里暂且不讨论这个类有什么用.我们来看一下onIoScheduler这个方法,首先进来这个onIoHandler一定是空为什么这么确定,我们进来RxJavaPlugins这个类里面看,这里面初始了很多FuncTion但是都没有赋值,所以都为空.所以第一次进来直接Return的是defaultScheduler这个,  defaultScheduler这个又是从上面io()方法里面传进了个IO,IO又是什么,

IO位于Schedules这个类里面,是一个static final类,他里面有个静态代码块,所以一进来就为IO初始化了,

static final Scheduler IO;

来看一下Scedulers里面初始化的部分代码,

public final class Schedulers {
        static final Scheduler IO;
    static {
        IO = RxJavaPlugins.initIoScheduler(new Callable<Scheduler>() {
            @Override
            public Scheduler call() throws Exception {
                return IoHolder.DEFAULT;
            }
        });
    }

}

这里我们只关注一下IO这个静态变量,下面这行代码就有点意思,这种写法在ActivityService里面获取一个IBinder也有过,值得借鉴

RxJavaPlugins.initIoScheduler(..)在这个方法时需要传入一个Callable接口,这个接口直接是返回传入的泛型,就如上面代码Callable<Scheduler>传入的是Scheduler返回的也是Scheduler

public interface Callable<V> {

    V call() throws Exception;//泛型是什么返回的就是什么,而返回的是交给实现类来实现
}

所以这里我们返回的是一个IoHolder.DEFAULT,也就是直接new IoScheduler(),所以这个IO就是IoHolder

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


    public IoScheduler() {
        this(WORKER_THREAD_FACTORY);
    }

    public IoScheduler(ThreadFactory threadFactory) {
        this.threadFactory = threadFactory;
        this.pool = new AtomicReference<CachedWorkerPool>(NONE);
        start();
    }
    public void start() {
        CachedWorkerPool update = new CachedWorkerPool(KEEP_ALIVE_TIME, KEEP_ALIVE_UNIT, threadFactory);
        if (!pool.compareAndSet(NONE, update)) {
            update.shutdown();
        }
    }

最后我们再返回到最开始

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

这个IO我们已经知道了是IoHolder,所以当我们subscribeOn(Schedulers.io())的时候就是subscribeOn(IoHolder),这下我们可以分析subscribeOn这个谅

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

简单,直接是new了一个ObservableSubscribeOn,把当前Observable和传过来的IoHolder当个参数给传进去,到了这里,其实就跟之前map操作符一个样,当我们和下游关联的时候,就会进入到下面这个方法.

    public void subscribeActual(final Observer<? super T> s) {
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);

        s.onSubscribe(parent);

        parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
            @Override
            public void run() {
                source.subscribe(parent);
            }
        }));
    }

上面代码可以分析出,我们的上游发射的方法 source.subscribe(parent)是在一个run()里执行,这就如果在subscribe之前不将线程切换到主线程,那么上游和下游都是在IO线程里面操作.

最终会走到ObservableCreate创建操作符的下面这个方法里

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

而这个方法的observer将原始的observer在ObservableSubscribeOn这个被观察者里给替换成了他自己的SubscribeOnObserver

总结

第一步:

先是通过create方法创建了一个ObserableCreate(被观察者)-------->通过map(转换操作符)---->转成被观察者(ObserableMap)----->再通过上游的线程操作符切换成了ObservableSubscribeOn(也是被观察者)----->再通过subscribe这个方法关联上游和下游---->这里会创建一个观察者Observer

第二步

Observable.subscribe这方法里里,由于是了后一个被观察者是ObservableSubscribeOn,所以流程如下

ObservableSubscribeOn.subscribeActual(Observer)---->将传入的observer封装成了自己的SubscribeOnObserver

----->执行Observer.onSubscribe(..)保持这个方法在原有的线程

---->ObserableMap.subscribeActual(subscribeOnObserver)--->将传入的subscribeOnObserver封装成MapObserver

---->ObserableCreate.subscribeActual(mapObserver)

第三步

第二步中最后到的是ObserableCreate.subscribeActual(mapObserver),这个时候是在IO线程中操作的

先是创建一个发射器CreateEmitter

CreateEmitter<T> parent = new CreateEmitter<T>(observer);

然后

mapObserver.onSubscribe(..)--->subscribeOnObserver.onSubscribe(..)------>

在subscribeOnObserver.onSubscribe这个方法会判断是不是已经执行过了这个方法,因为当上游和下游关联的时候,如果走了线程切换会在ObservableSubscribeOn的subscribeActual方法里执行一次,保证关联成功的第一个方法运行在最开始的线程里面.

----->下游的onSubscribe不在这执行

----->ObserableCreate.subscribe(parent)  把创建的发射器传入进来

----->上游的parent.onNext("111111)  在这里就开始发射了一个onNext事件

----->下游开始接收事件mapObserver.onNext("111111)

----->mapObserver会执行Function.apply("111111"),将"111111"转为404

----->subscribeOnObserver.onNext(404)

----->最后就到observer.onNext(404)

 

如果再执行.observeOn(AndroidSchedulers.mainThread())其实就是多了一个ObservableObserveOn观察者

ObservableSubscribeOn SubscribeOnObserver上游线程切换,他只会影响上游的发射事件线程

 

ObservableObserveOn    ObserveOnObserver下游线程切换,只会影响下游接收事件线程

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章