詳解Rxjava原理,其實沒有那麼難

一、基礎知識

RxJavaPlugins.onAssembly(new SingleJust<T>(item));
這個方法的作用設什麼呢,其實它的作用就是一個轉換作用。使用的hook技術,這裏原理比較難懂 暫時理解成會轉換成 new出來的對象吧。

/**
 * Calls the associated hook function.
 * @param <T> the value type
 * @param source the hook's input value
 * @return the value returned by the hook
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
@NonNull
public static <T> Single<T> onAssembly(@NonNull Single<T> source) {
    Function<? super Single, ? extends Single> f = onSingleAssembly;
    if (f != null) {
        return apply(f, source);
    }
    return source;
}

二、最簡單的調用

Single.just("1")
      .subscribe(new SingleObserver<String>() {
          @Override
          public void onSubscribe(Disposable d) {

          }

          @Override
          public void onSuccess(String s) {

          }

          @Override
          public void onError(Throwable e) {

          }
      });

這段代碼很簡單的調用,裏面的邏輯就是 Single.just 會產生一個SingleJust 對象然後調用父類的 subscribe 方法,在這個方法中最終還是調用的自己的subscribeActual 方法, 這個方法的參數是 SingleObserver 。

protected void subscribeActual(SingleObserver<? super T> s) {
    s.onSubscribe(Disposables.disposed());
    s.onSuccess(value);
}

最後得到結果就是SingleObserver 的onSubscribe 和 onSuccess 方法被調用。

三、加點難度 加入Map操作符以後是怎麼調用呢?

Single.just("1")
        .map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) throws Exception {
                return Integer.valueOf(s);
            }
        })
        .subscribe(new SingleObserver<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {
            }
            @Override
            public void onSuccess(Integer integer) {
            }
            @Override
            public void onError(Throwable e) {
            }
        });

看看這個是如何回調成功呢?
首先還是創建一個SingleJust 調用map操作符,返回一個SingleMap 對象,然後調用去subscribe訂閱 SingleObserver ,最終方法往回調用,到達 SingleMap 的 subscribeActual 並傳入觀察者對象SingleObserver。

source.subscribe(new MapSingleObserver<T, R>(t, mapper));

這裏的source 是SingleJust , t是SingleObserver 對象 ,mapper 是map操作符傳入的一個函數方法。

接下來看SingleJust的subscribe 如何調用的? 依然是父類的 subscribeActual傳入的參數是 MapSingleObserver
最終調用了

protected void subscribeActual(SingleObserver<? super T> s) {
    s.onSubscribe(Disposables.disposed());
    s.onSuccess(value);
}

跟上一步一樣調用了這個方法,只不過這裏的觀察者是MapSingleObserver。 看看它的onSubscribe 和 onSuccess 做了些什麼事。

public void onSuccess(T value) {
    R v;
    try {
        v = ObjectHelper.requireNonNull(mapper.apply(value), "The mapper function returned a null value.");
    } catch (Throwable e) {
        Exceptions.throwIfFatal(e);
        onError(e);
        return;
    }
    t.onSuccess(v);
}

顯示調用mapper的apply方法 也就是map 的那個轉換操作的方法。 轉換以後的值 作爲的t的onSuccess 參數。也就是SingleObserver的onSuccess 被調用了。

小結一下:
在這裏插入圖片描述

1、從上到下調用過程中不停包裝被觀察者,顯示SingleJust 然後到 SingleMap,soure就是自己上一層對象的引用
2、當遇到subscribe是 就一次調用每個被觀察這的訂閱功能, 顯示SingleMap.subscribe(SingleObserver) 然後 把SingleObserver包裝成MapSingleObserver 交給SingleJust 訂閱, 一直到數據源位置,調用對象的onSubscribe ,onSuccess
3、從數據源 在一次調用每個被包裝的 observer的onsuccess 方法,直到最後的 SingleObserver 的方法被調用

套路就是被觀察者 (Single、Observable)沒遇到一個操作符都把自己包裝一層,然後用source 記錄上一層的引用, 知道遇到subscribe 訂閱方法,會創建一個觀察者SingleObserver, 然後內部一次包裝上一層的被觀察這對象需要訂閱的觀察者。 如 SingleMap 訂閱 SingleObserver,然後 SingleJust 訂閱 MapSingleObserver 。 最後 調用終點的數據源的回調方法,onSuccess 。 在一次回調每一層的Observer 方法直到調用結束。

四、再加一點難度,加上線程操作符

Single.just("1")
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new SingleObserver<String>() {
            @Override
            public void onSubscribe(Disposable d) {
            }
            @Override
            public void onSuccess(String integer) {
            }
            @Override
            public void onError(Throwable e) {
            }
        });

爲了理解起來不那麼喫力,將map操作符暫時先去掉。

第一步 和第二步

根據 前面兩節總結的套路,每次遇到操作符就創建對應的一個包裹被觀察者,所以subscribeOn操作符 創建了 SingleSubscribeOn被觀察者 ,然後 observeOn 創建了 SingleObserveOn被觀察者。他們分別訂閱了下一級穿過來的觀察者。
SingleObserveOn 訂閱了 SingleObserver, 幷包裝了一個 ObserveOnSingleObserver

// 這是SingleObserveOn 處理訂閱的方法
protected void subscribeActual(final SingleObserver<? super T> s) {
    source.subscribe(new ObserveOnSingleObserver<T>(s, scheduler));
    // source 是SingleSubscribeOn 
}
//這是SingleSubscribeOn處理訂閱的方法
protected void subscribeActual(final SingleObserver<? super T> s) {
    final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s, source);
    s.onSubscribe(parent);
    // 執行了線程切換,至於怎麼線程切換先暫時不要關注,只是測試的parent ,如果在此訂閱就是另外一個線程了,可以簡單理解把parent 丟到另一個線程中了,執行了run方法
    Disposable f = scheduler.scheduleDirect(parent);
    parent.task.replace(f);
}

// 對應的查看SubscribeOnObserver 的run方法
    static final class SubscribeOnObserver<T>
    extends AtomicReference<Disposable>
    implements SingleObserver<T>, Disposable, Runnable {
        ...//一些其他的方法
        @Override
        public void run() {
            source.subscribe(this);
            //在線程中完成了訂閱
        }
    }

按照訂閱的執行順序.subscribe -> observeOn -> subscribeOn -> just, 所以先是SingleObserveOn 訂閱 SingleObserver,把SingleObserver包裝成ObserveOnSingleObserver,交給SingleSubscribeOn訂閱(啓動了一個線程,在run方法中完成的訂閱),並在包裝一層得到一個 ObserveOnSingleObserver 交給 SingleJust進行 回調。

可以看到observeOn中並沒有做任何操作,而subscribeOn 執行了一些特殊的代碼。scheduler.scheduleDirect(parent)註釋中我已經說明清楚。 所以到了SingleJust 數據源回調的時候,就是在newthread 線程中執行的。

第三步

執行從數據源開始執行回調,首頁是SingleJust執行了onSuccess方法。 看一下 subscribeOn操作符創建被觀察者SingleSubscribeOn 對應的觀察者 ObserveOnSingleObserver的回調方法如何執行呢?

SubscribeOnObserver(SingleObserver<? super T> actual, SingleSource<? extends T> source) 
    this.actual = actual;
    this.source = source;
    this.task = new SequentialDisposable();
}
@Override
public void onSubscribe(Disposable d) {
    DisposableHelper.setOnce(this, d);
}
@Override
public void onSuccess(T value) {
    actual.onSuccess(value);
}
@Override
public void onError(Throwable e) {
    actual.onError(e);
}

這裏的actual就是它的下一層 observeOn創建的被觀察者 SingleObserveOn 對應的觀察者 ObserveOnSingleObserver 執行回調方法了

ObserveOnSingleObserver(SingleObserver<? super T> actual, Scheduler scheduler) {
    this.actual = actual;
    this.scheduler = scheduler;
}
@Override
public void onSubscribe(Disposable d) {
    if (DisposableHelper.setOnce(this, d)) {
        actual.onSubscribe(this);
    }
}

@Override
public void onSuccess(T value) {
    //value 是從數據源一步步會掉回來的值
    this.value = value;
    //同樣是完成了線程切換 但是它並沒有執行下一步操作的回調。 如果不回調等於鏈條就斷了,所以一定有回調,假設一下,線程切換執行就會在 run方法中執行回調
    Disposable d = scheduler.scheduleDirect(this);
    DisposableHelper.replace(this, d);
}

@Override
public void onError(Throwable e) {
    this.error = e;
    Disposable d = scheduler.scheduleDirect(this);
    DisposableHelper.replace(this, d);
}

@Override
public void run() {
    Throwable ex = error;
    if (ex != null) {
        actual.onError(ex);
    } else {
        //完成了線程操作以後, 執行run方法,然後繼續回調
        actual.onSuccess(value);
        //actual 是 observeOn 創建的 SingleObserver ,至此我們就得到了想要的結果,回調鏈結束
    }
}

observeOn 的 onSuccess 方法中切換了線程 在對應的 run方法中完成的下一層的回調
actual 是 observeOn 創建的 SingleObserver ,至此我們就得到了想要的結果,回調鏈結束。
在這裏插入圖片描述

分析subscribeOn 和 observeOn是如何完成線程切換的

subscribeOn 對應的 SingleSubscribeOn 被觀察者的訂閱方法

protected void subscribeActual(final SingleObserver<? super T> s) {
    final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s, source);
    s.onSubscribe(parent);
    //parent作爲一個
    Disposable f = scheduler.scheduleDirect(parent);
    parent.task.replace(f);
}
    public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
        final Worker w = createWorker();

        final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);

        DisposeTask task = new DisposeTask(decoratedRun, w);

        w.schedule(task, delay, unit);

        return task;
    }

從代碼上看它創建了一個worker 然後執行了schedule , 因爲我們newThread 對應是NewThreadWorker(猜的),看看它的schedule執行了什麼。

    public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
        //run 就是 前面的parent 它是一個觀察者(SubscribeOnObserver), 
        Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
        //繼續對這個 Runnable進行包裝
        ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);

        if (parent != null) {
            if (!parent.add(sr)) {
                return sr;
            }
        }

        Future<?> f;
        try {
            if (delayTime <= 0) {
                // 最後執行了submit  
                // executor ==    private final ScheduledExecutorService executor;
                // 執行了線程池 ,所以SubscribeOnObserver 的run就會被調用
                f = executor.submit((Callable<Object>)sr);
            } else {
                f = executor.schedule((Callable<Object>)sr, delayTime, unit);
            }
            sr.setFuture(f);
        } catch (RejectedExecutionException ex) {
            if (parent != null) {
                parent.remove(sr);
            }
            RxJavaPlugins.onError(ex);
        }

        return sr;
    }

貼一下SubscribeOnObserver 的run方法

    static final class SubscribeOnObserver<T>
    extends AtomicReference<Disposable>
    implements SingleObserver<T>, Disposable, Runnable {
        
        @Override
        public void run() {
            //source 就是 SingleJust實例對象
            source.subscribe(this);
        }
    }

至此,subscribeOn 切換了訂閱線程。 簡單說讓上一層的訂閱在線程中執行。

observeOn 控制的是回調執行的線程,也就是 onSucess 或者 map操作符對應的函數方法執行的線程。
observeOn 對應的被觀察者是 SingleObserveOn 對應的觀察者是ObserveOnSingleObserver 所以我們直接去看看一下它的回調方法是如何執行的。

static final class ObserveOnSingleObserver<T> extends AtomicReference<Disposable>
implements SingleObserver<T>, Disposable, Runnable {

    ObserveOnSingleObserver(SingleObserver<? super T> actual, Scheduler scheduler) {
        this.actual = actual;
        this.scheduler = scheduler;
    }
    // 刪掉了一些對於的方法
    @Override
    public void onSuccess(T value) {
        this.value = value;
        // 執行了線程操作,根據subscribeOn操作符的經驗,這一句代碼,主要是爲了執行this 的潤方法, 而run方法中正好是執行了對應的回調方法。
        Disposable d = scheduler.scheduleDirect(this);
        DisposableHelper.replace(this, d);
    }

    @Override
    public void run() {
        Throwable ex = error;
        if (ex != null) {
            actual.onError(ex);
        } else {
            actual.onSuccess(value);
        }
    }
  
}

看看scheduler.scheduleDirect

public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    final Worker w = createWorker();
    final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
    DisposeTask task = new DisposeTask(decoratedRun, w);
    w.schedule(task, delay, unit);
    return task;
}

一模一樣的代碼,創建一個worker 然後執行schedule,如何執行的?因爲使用的是 AndroidSchedulers.mainThread() 所以對應的 Worker 猜測是HandlerScheduler 看看它的schedule

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");
    if (disposed) {
        return Disposables.disposed();
    }
    run = RxJavaPlugins.onSchedule(run);
    ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);
    Message message = Message.obtain(handler, scheduled);
    message.obj = this; // Used as token for batch disposal of this worker's runnables.
    handler.sendMessageDelayed(message, unit.toMillis(delay));
    // Re-check disposed state for removing in case we were racing a call to dispose().
    if (disposed) {
        handler.removeCallbacks(scheduled);
        return Disposables.disposed();
    }
    return scheduled;
}

是不是特別熟悉 handler.sendMessageDelayed 發送消息到主線程去執行(猜的)。

看看 AndroidSchedulers.mainThread() 創建是什麼 Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));主線程的handler 的包裹對象。
這個包裹對象被扔給了SingleObserveOn 被觀察者,然後傳遞給了它對應的觀察者 ObserveOnSingleObserver 最終執行了

public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    final Worker w = createWorker();
    final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
    DisposeTask task = new DisposeTask(decoratedRun, w);
    w.schedule(task, delay, unit);
    return task;
}

HandlerScheduler

public Worker createWorker() {
    return new HandlerWorker(handler);
}

所以最後實質就是調用了MainHandler的run方法。

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