通過源碼來理解RxJava是切換到主線程的?

轉載請註明出處,謝謝https://blog.csdn.net/HarryWeasley/article/details/105363078

下方是一個最簡單切換線程的方式,本篇文章以下方的代碼引入。

 Observable.create(new ObservableOnSubscribe<String>() {
                    @Override
                    public void subscribe(ObservableEmitter<String> e) throws Exception {
                        e.onNext("1");
                        e.onNext("2");
                        e.onComplete();
                    }
                })
                        //切換到子線程
                        .subscribeOn(Schedulers.io())
                        //切換主線程
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Observer<String>() {
                            @Override
                            public void onSubscribe(Disposable d) {

                            }

                            @Override
                            public void onNext(String value) {
                                Log.d(TAG, "this is result"+value);
                            }

                            @Override
                            public void onError(Throwable e) {

                            }

                            @Override
                            public void onComplete() {

                            }
                        });

如上的代碼,當我們調用了observeOn(AndroidSchedulers.mainThread())這句話,就切換了到主線程,現在跟着源碼看看,rxJava是如何操作的。
Observable類:

 public final Observable<T> observeOn(Scheduler scheduler) {
        return observeOn(scheduler, false, bufferSize());
    }

public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
    //檢查schedule是否爲null
        ObjectHelper.requireNonNull(scheduler, "scheduler is null");
        //檢查bufferSize是否大於0,默認是128
        ObjectHelper.verifyPositive(bufferSize, "bufferSize");
        return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
    }

進入到RxJavaPlugins.onAssembly這個方法中
RxJavaPlugins類:

public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
//這裏是個hook機制,onObservableAssembly默認是null
        Function<? super Observable, ? extends Observable> f = onObservableAssembly;
        if (f != null) {
            return apply(f, source);
        }
        //f爲null,直接返回source,這裏是ObservableObserveOn
        return source;
    }

註釋已經寫明瞭,所以我們直接看傳入的ObservableObserveOn
ObservableObserveOn類:

 //本例是 AndroidSchedulers.mainThread()
    final Scheduler scheduler;
    ...
    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 {
            //生成了一個worker,這裏是重點1
            Scheduler.Worker w = scheduler.createWorker();
            //用ObserveOnObserver訂閱上游數據源。這樣當數據從上游push下來,會由ObserveOnObserver對應的onXXX()處理
            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
        }
    }

這裏有個重點需要注意一些scheduler.createWorker(),返回了一個worker,之後會進行解釋。

現在,我們看下ObserveOnObserver類的部分方法,還是那句話,本篇文章,主要是查看如何切換到主線程的

ObserveOnObserver類:

static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
    implements Observer<T>, Runnable {

     ...

        @Override
        public void onNext(T t) {
            // 執行過error / complete 會是true
            if (done) {
                return;
            }

            // 如果數據源類型不是異步的, 默認不是
            if (sourceMode != QueueDisposable.ASYNC) {
                // 將上游push過來的數據 加入 queue裏
                queue.offer(t);
            }
            //開始進入對應Workder線程,在線程裏 將queue裏的t 取出 發送給下游Observer
            schedule();
        }

        ...


         void schedule() {
            if (getAndIncrement() == 0) {
                //將ObserveOnObserver(實現了Runnable)加入worker,這裏是重點2
                worker.schedule(this);
            }
        }
        
        ...

    }

在schedule調用了worker.schedule(this)方法,我們可以思考,在這邊將Runnable加入了worker中,那麼一定會調用其實現的run方法,而run方法裏就是主線程了

我們去看內部調用方法:

Scheduler類:

 public Disposable schedule(@NonNull Runnable run) {
            return schedule(run, 0L, TimeUnit.NANOSECONDS);
        }

//抽象方法,所以我們要找到實現它的類
public abstract Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit);

這裏的schedule是AndroidSchedulers.mainThread(),那麼我們去這個類去看看,

//AndroidSchedulers類:
   public static Scheduler mainThread() {
        return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
}

//RxAndroidPlugins類
  public static Scheduler onMainThreadScheduler(Scheduler scheduler) {
        if (scheduler == null) {
            throw new NullPointerException("scheduler == null");
        }
        //其實這裏還是一個hook機制,默認這邊的onMainThreadHandler爲null
        Function<Scheduler, Scheduler> f = onMainThreadHandler;
        if (f == null) {
            //直接返回傳入的scheduler
            return scheduler;
        }
        return apply(f, scheduler);
    }

通過上方的代碼分析,那麼直接看MAIN_THREAD是如何生成的,繼續看代碼:

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

//RxAndroidPlugins類:
public static Scheduler initMainThreadScheduler(Callable<Scheduler> scheduler) {
        if (scheduler == null) {
            throw new NullPointerException("scheduler == null");
        }
        //又是一個hook機制,onInitMainThreadHandler默認爲null
        Function<Callable<Scheduler>, Scheduler> f = onInitMainThreadHandler;
        if (f == null) {
            //返回這個方法
            return callRequireNonNull(scheduler);
        }
        return applyRequireNonNull(f, scheduler);
    }

//RxAndroidPlugins類:
static Scheduler callRequireNonNull(Callable<Scheduler> s) {
        try {
            //這邊調用了call方法,拿到scheduler,並且返回
            Scheduler scheduler = s.call();
            if (scheduler == null) {
                throw new NullPointerException("Scheduler Callable returned null");
            }
            return scheduler;
        } catch (Throwable ex) {
            throw Exceptions.propagate(ex);
        }
    }

通過 Scheduler scheduler = s.call();這個方法得知,最上面的call代碼返回的值,就是這個scheduler,就是這個MainHolder.DEFAULT。
AndroidSchedulers類:

 private static final class MainHolder {
       //最終的scheduler方法
        static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));
    }

可以看出來,這裏傳入了一個主線程的Handler

我們去看看HandlerScheduler類方法

HandlerScheduler類:

final class HandlerScheduler extends Scheduler {

    //主線程的handler
    private final Handler handler;

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

    ...

     @Override
    public Worker createWorker() {
        //這裏不就是重點1,調用的方法嗎,所以worker就是HandlerWorker
        return new HandlerWorker(handler);
    }


}

從上面的代碼,我們終於找到了worker的實現類了,我們找到了worker類,那麼我們就去找重點2的那個方法,看實現的schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit)的具體實現代碼。

去看HandlerWorker的實現方法

 //HandlerWorker類
 public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
            
            ...
            hook機制,其實就是獲取到run
            run = RxJavaPlugins.onSchedule(run);

            //一個代理類,其實還是一個實現的Runnable的類
            ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);

            //獲取到message,將scheduled賦值到callBack裏
            Message message = Message.obtain(handler, scheduled);
            message.obj = this; // Used as token for batch disposal of this worker's runnables.

            //handler發送消息,delay是0
            handler.sendMessageDelayed(message, unit.toMillis(delay));

            ...
 
            return scheduled;
        }


//Message類
public static Message obtain(Handler h, Runnable callback) {
        Message m = obtain();
        m.target = h;
        //給message的callback賦值上面的Runnable
        m.callback = callback;

        return m;
    }  

上面的代碼,獲取到一個message,然後直接通過handler發送消息,這個handler之前已經說過,是一個主線程Looper.getMainLooper()的handler。其實之後,就是handler機制了的,最終主線程的Looper循環,獲取到message信息,最終會調用handler的dispatchMessage方法。

public void dispatchMessage(@NonNull Message msg) {
    //這裏已經是主線程了
        if (msg.callback != null) {
            //之前將其callback賦值了,所以會執行此地方的代碼
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            //這裏不就是我們正常情況下,自定義handler處理代碼的地方嗎
            handleMessage(msg);
        }
    }


     private static void handleCallback(Message message) {
        //從這裏可以看到,調用了callback的run方法
        message.callback.run();
    }

這裏可以自己敲代碼驗證一下,例子如下:

 case R.id.btn10:
 //button點擊後,發送一個消息
                Handler handler = new Handler(Looper.getMainLooper());
                myRunnable runnable = new myRunnable();
                Message message = Message.obtain(handler, runnable);
                handler.sendMessage(message);
                break;

...
 class myRunnable implements java.lang.Runnable {

        @Override
        public void run() {
            Log.d(TAG, "這裏執行了" + Thread.currentThread());
        }
    }

執行結果爲:這裏執行了Thread[main,5,main]

從上面的代碼知道,就是傳入的message的callback執行了run方法,callback就是代理類ScheduledRunnable,那我們看下他的run方法

private static final class ScheduledRunnable implements Runnable, Disposable {

 @Override
        public void run() {
            try {
                //這裏已經是主線程了
                //這裏的delegate就是重點2傳入的Runnable,也就是ObserveOnObserver
                delegate.run();
            } catch (Throwable t) {
                RxJavaPlugins.onError(t);
            }
        }
 }

從上面的代碼中,可知,通過消息機制,已經進入了主線程,這個時候,再調用ObserveOnObserver的run方法,我們繼續看代碼

  static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
    implements Observer<T>, Runnable {

       ...
       @Override
        public void run() {
            //從這裏開始,這個方法已經是在Workder對應的線程裏執行的了
            //默認是false
            if (outputFused) {
                drainFused();
            } else {
                drainNormal();
            }
        }
        ...


 void drainNormal() {
            int missed = 1;

            final SimpleQueue<T> q = queue;
            final Observer<? super T> a = actual;

            for (;;) {
                // 如果已經 終止 或者queue空,則跳出函數,
                if (checkTerminated(done, q.isEmpty(), a)) {
                    return;
                }

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

                    try {
                        //從queue裏取出一個值
                        v = q.poll();
                    } catch (Throwable ex) {
                        //異常處理 並跳出函數
                        Exceptions.throwIfFatal(ex);
                        s.dispose();
                        q.clear();
                        a.onError(ex);
                        worker.dispose();
                        return;
                    }
                    ...
                    
                    //發送給下游了
                    a.onNext(v);
                }

                ...
            }
        }
    }

從上面,就看出來了,在下游的onNext方法裏,已經變成了主線程了。

總結:

  1. ObserveOnObserver實現了Observer和Runnable接口。
  2. 在onNext()裏,先不切換線程,將數據加入隊列queue。然後開始切換線程,在另一線程中,從queue裏取出數據,push給下游Observer
  3. 所以observeOn()影響的是其下游的代碼,且多次調用仍然生效。
  4. 因爲其切換線程代碼是在Observer裏onXXX()做的,這是一個主動的push行爲(影響下游)。
  5. 關於多次調用生效問題,observeOn()是一個主動的行爲,每次切換線程後會立刻發送數據,在OnXXX()方法裏執行代碼,所以會生效多次.
  6. 最終能切換到主線程,是通過消息機制,主線程的looper一直循環獲取MessageQueue的message消息,然後調用他的callback.run方法

這樣整個切換到主線程的流程已經分析完了。之後的文章,我準備再分析下切換子線程的流程,其實流程是大同小異的。
本篇文章結束。

參考文章:https://www.jianshu.com/p/6ef45f8ee79d

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