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下游線程切換,只會影響下游接收事件線程

 

 

 

 

 

 

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