【源碼分析】RxJava 1.2.2 實現簡單事件流的原理

目前RxJava已經被廣泛用於Android開發中,GitHub地址在這,官方文檔說2018.03.31停止維護1.x 版本,本篇文章基於RxJava 1.2.2

關於RxJava的介紹文章推薦看扔物線給 Android 開發者的 RxJava 詳解,這篇文章講解了很多使用方法、結論和部分原理,雖然是兩年前的文章,但現在看還是有不少的收穫。

常用的類和接口

在正式開始分析之前,我們先來回顧一下RxJava中常用的一些類和接口,以利於後面的分析。

被觀察者-類Observable,RxJava中核心的類,事件的生產者,它的大量操作符可以將一個Observable轉換爲另一個Observable。它有一個成員變量onSubscribe

public class Observable<T> {

    final OnSubscribe<T> onSubscribe;

    public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
        // cover for generics insanity
    }
}

觀察者-接口Observer,事件的消費者。

public interface Observer<T> {

    void onCompleted();

    void onError(Throwable e);

    void onNext(T t);
}

訂閱-接口Subscription,被觀察者和觀察者形成訂閱關係後,就有返回一個訂閱,便於取消訂閱。

public interface Subscription {

    void unsubscribe();

    boolean isUnsubscribed();
}

訂閱者-抽象類Subscriber,實現了接口Observer和Subscription ,所以它可以接收事件,也可以取消訂閱。事實上,在訂閱過程中,Observer 也總會先被轉換成一個 Subscriber 再使用。

public abstract class Subscriber<T> implements Observer<T>, Subscription {
    public void onStart() {
        // do nothing by default
    }
}

接口Function、Action系列,這些接口都有一個call()方法,接口名中的數字代表call()方法中的參數個數,區別在於Function系列的方法有返回值,而Action系列的方法沒有返回值。

public interface Function {

}

public interface Func1<T, R> extends Function {
    R call(T t);
}

public interface Action extends Function {

}

public interface Action1<T> extends Action {
    void call(T t);
}

簡單的事件流

下面的例子可以說是最簡單的使用示例,創建一個被觀察者,然後和觀察者形成訂閱關係。訂閱後,被觀察者調用3次onNext()方法,然後結束。本篇文章就從這段簡單的代碼入手,探究RxJava背後的原理。

Observable
        .create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("消息1");
                subscriber.onNext("消息2");
                subscriber.onNext("消息3");
                subscriber.onCompleted();
            }
        })
        .subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                System.out.println("任務結束");
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("任務出錯");
            }

            @Override
            public void onNext(String s) {
                System.out.println(s);
            }
        });

create()

public static <T> Observable<T> create(OnSubscribe<T> f) {
    return new Observable<T>(RxJavaHooks.onCreate(f));
}

protected Observable(OnSubscribe<T> f) {
    this.onSubscribe = f;
}

第2行有一個RxJavaHooks,之後我們會看到在RxJavahook頻繁地出現,它的返回值類型和入參類型都一樣。爲簡化分析,抓住重點,本篇文章不會對hook相關部分深入探究。

第5行將對成員變量onSubscribe賦值。

很明顯,create()方法的作用就是將傳入的onSubscribe賦值給成員變量onSubscribe

subscribe()

public final Subscription subscribe(Subscriber<? super T> subscriber) {
    return Observable.subscribe(subscriber, this);
}

static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
 // validate and proceed
    if (subscriber == null) {
        throw new IllegalArgumentException("subscriber can not be null");
    }
    if (observable.onSubscribe == null) {
        throw new IllegalStateException("onSubscribe function can not be null.");
        /*
         * the subscribe function can also be overridden but generally that's not the appropriate approach
         * so I won't mention that in the exception
         */
    }

    // new Subscriber so onStart it
    subscriber.onStart();

    /*
     * See https://github.com/ReactiveX/RxJava/issues/216 for discussion on "Guideline 6.4: Protect calls
     * to user code from within an Observer"
     */
    // if not already wrapped
    if (!(subscriber instanceof SafeSubscriber)) {
        // assign to `observer` so we return the protected version
        subscriber = new SafeSubscriber<T>(subscriber);
    }

    // The code below is exactly the same an unsafeSubscribe but not used because it would
    // add a significant depth to already huge call stacks.
    try {
        // allow the hook to intercept and/or decorate
        RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);
        return RxJavaHooks.onObservableReturn(subscriber);
    } catch (Throwable e) {
        // special handling for certain Throwable/Error/Exception types
        Exceptions.throwIfFatal(e);
        // in case the subscriber can't listen to exceptions anymore
        if (subscriber.isUnsubscribed()) {
            RxJavaHooks.onError(RxJavaHooks.onObservableError(e));
        } else {
            // if an unhandled error occurs executing the onSubscribe we will propagate it
            try {
                subscriber.onError(RxJavaHooks.onObservableError(e));
            } catch (Throwable e2) {
                Exceptions.throwIfFatal(e2);
                // if this happens it means the onError itself failed (perhaps an invalid function implementation)
                // so we are unable to propagate the error correctly and will just throw
                RuntimeException r = new OnErrorFailedException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);
                // TODO could the hook be the cause of the error in the on error handling.
                RxJavaHooks.onObservableError(r);
                // TODO why aren't we throwing the hook's return value.
                throw r; // NOPMD
            }
        }
        return Subscriptions.unsubscribed();
    }
}

第19行調用了subscriberonStart()方法,我們可以在這個方法裏做一些準備工作。

第35行調用了onSubscribecall()方法,參數爲Subscriber, 這個方法來自於它繼承的接口Action1,而我們在call()方法中調用了觀察者的onNext()onCompleted()方法,被觀察者開始發送事件,由此實現了事件由被觀察者向觀察者的傳遞。

這裏分析的Observable是由create()方法創建的,我們手動在call()方法中調用了觀察者的onNext()onCompleted()方法。Observable也可以由just()from()方法創建,這些方法創建的被觀察者會自動調用觀察者的onNext()onCompleted()onError方法,我們只需要傳入簡單的參數就可以了,但本質上和用create()方法創建是一樣的。

subscribe()的不同重載方法還接受Action1Observer形式的參數,但它們都會被轉換爲Subscriber,最終進入剛纔分析的subscribe()方法中。

至此,一次簡單的事件流就清楚了:

  1. 賦值給成員變量onSubscribe
  2. 調用subscribe()方法訂閱,回調onSubscribecall()方法,傳入Subscriber作爲參數,於是在call()方法中可以調用Subscriber的相關方法發送事件。
  3. 注意:只有在訂閱後纔開始發送事件。

線程調度

Observable中有大量的操作符可以實現變換,一般用的最多的估計就是線程調度了。我們給之前的例子加上Android中常用的線程切換:

Observable
        .create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("消息1");
                subscriber.onNext("消息2");
                subscriber.onNext("消息3");
                subscriber.onCompleted();
            }
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                System.out.println("任務結束");
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("任務出錯");
            }

            @Override
            public void onNext(String s) {
                System.out.println(s);
            }
        });

注意:使用AndroidSchedulers.mainThread()需要導入RxAndroid

我們來分析這段代碼中線程調度實現的原理,接下來涉及的源碼比較多,我們從序號1開始對源碼片段作標記。

subscribeOn()

//第1段代碼
public final Observable<T> subscribeOn(Scheduler scheduler) {
     if (this instanceof ScalarSynchronousObservable) {
         return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler);
     }
     return create(new OperatorSubscribeOn<T>(this, scheduler));
 }

可以看到,調用subscribeOn()方法後返回了一個新的Observable

第3行的判斷在此時爲false,我們直接看第6行,這個OperatorSubscribeOn是新的ObservableOnSubscribe,跟進OperatorSubscribeOn一探究竟。

//第2段代碼
//rx.internal.operators.OperatorSubscribeOn
public final class OperatorSubscribeOn<T> implements OnSubscribe<T> {

    final Scheduler scheduler;
    final Observable<T> source;

    public OperatorSubscribeOn(Observable<T> source, Scheduler scheduler) {
        this.scheduler = scheduler;
        this.source = source;
    }

    @Override
    public void call(final Subscriber<? super T> subscriber) {
        final Worker inner = scheduler.createWorker();
        subscriber.add(inner);

        inner.schedule(new Action0() {
            @Override
            public void call() {
                final Thread t = Thread.currentThread();

                Subscriber<T> s = new Subscriber<T>(subscriber) {
                    @Override
                    public void onNext(T t) {
                        subscriber.onNext(t);
                    }

                    @Override
                    public void onError(Throwable e) {
                        try {
                            subscriber.onError(e);
                        } finally {
                            inner.unsubscribe();
                        }
                    }

                    @Override
                    public void onCompleted() {
                        try {
                            subscriber.onCompleted();
                        } finally {
                            inner.unsubscribe();
                        }
                    }

                    @Override
                    public void setProducer(final Producer p) {
                        subscriber.setProducer(new Producer() {
                            @Override
                            public void request(final long n) {
                                if (t == Thread.currentThread()) {
                                    p.request(n);
                                } else {
                                    inner.schedule(new Action0() {
                                        @Override
                                        public void call() {
                                            p.request(n);
                                        }
                                    });
                                }
                            }
                        });
                    }
                };

                source.unsafeSubscribe(s);
            }
        });
    }
}

在構造方法中,第9行和第10行分別保存了傳入的ObservableScheduler

OperatorSubscribeOn作爲新的ObservableOnSubscribe,根據之前對subscribe()方法的分析,它的call()方法將在訂閱後被回調。那我們就來看一下它的call方法:

第15行創建了Worker類型的變量inner,爲保持主邏輯的清晰,暫時先不管Worker是什麼,繼續看主邏輯。

先透露一下,調用第18行的schedule()方法後,最終將進入第20行的call()方法。

第23行創建了一個Subscriber,第67行的source就是剛纔構造方法中傳入的Observable,即上游Observable,這裏將剛纔創建的Subscriber作爲參數傳入了它的unsafeSubscribe()方法,繼續跟進:

//第3段代碼
//rx.Observable
public final Subscription unsafeSubscribe(Subscriber<? super T> subscriber) {
    try {
        // new Subscriber so onStart it
        subscriber.onStart();
        // allow the hook to intercept and/or decorate
        RxJavaHooks.onObservableStart(this, onSubscribe).call(subscriber);
        return RxJavaHooks.onObservableReturn(subscriber);
    } catch (Throwable e) {
        // special handling for certain Throwable/Error/Exception types
        Exceptions.throwIfFatal(e);
        // if an unhandled error occurs executing the onSubscribe we will propagate it
        try {
            subscriber.onError(RxJavaHooks.onObservableError(e));
        } catch (Throwable e2) {
            Exceptions.throwIfFatal(e2);
            // if this happens it means the onError itself failed (perhaps an invalid function implementation)
            // so we are unable to propagate the error correctly and will just throw
            RuntimeException r = new OnErrorFailedException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);
            // TODO could the hook be the cause of the error in the on error handling.
            RxJavaHooks.onObservableError(r);
            // TODO why aren't we throwing the hook's return value.
            throw r; // NOPMD
        }
        return Subscriptions.unsubscribed();
    }
}

從方法名能猜出這也是一個訂閱方法,第6行更是和之前分析的subscribe()方法進行了相同的操作,調用了上游ObservableonSubscribecall()方法。

回到第2段代碼,第26、32、41行的代碼分別調用了下游Subscriber的對應方法。

至此,我們可以明白subscribeOn()究竟做了什麼:

  1. 該方法返回了一個新的Observable
  2. 新的Observable收到訂閱回調後,回調上游ObservableonSubscribecall()方法。
  3. 新的Observable中的OnSubscribecall回調中新建的Subscriber接收到事件後,繼續將事件傳遞給下游的Subscriber

那說好的子線程切換又在哪裏呢?

我們再回過頭看第2段代碼的Worker類,它由Scheduler創建而來。我們這裏使用的SchedulerSchedulers.io(),跟進看一下:

//第4段代碼
//rx.schedulers.Schedulers 只拷貝了相關核心代碼
public final class Schedulers {
    private final Scheduler ioScheduler;

    public static Scheduler io() {
        return RxJavaHooks.onIOScheduler(getInstance().ioScheduler);
    }

    private Schedulers() {
       @SuppressWarnings("deprecation")
       RxJavaSchedulersHook hook = RxJavaPlugins.getInstance().getSchedulersHook();

       Scheduler c = hook.getComputationScheduler();
       if (c != null) {
           computationScheduler = c;
       } else {
           computationScheduler = RxJavaSchedulersHook.createComputationScheduler();
       }

       Scheduler io = hook.getIOScheduler();
       if (io != null) {
           ioScheduler = io;
       } else {
           ioScheduler = RxJavaSchedulersHook.createIoScheduler();
       }

       Scheduler nt = hook.getNewThreadScheduler();
       if (nt != null) {
           newThreadScheduler = nt;
       } else {
           newThreadScheduler = RxJavaSchedulersHook.createNewThreadScheduler();
       }
   }
}

第25行表明了ioScheduler的出處:

//第5段代碼
//rx.plugins.RxJavaSchedulersHook 只拷貝了相關核心代碼
public class RxJavaSchedulersHook {
    public static Scheduler createIoScheduler() {
        return createIoScheduler(new RxThreadFactory("RxIoScheduler-"));
    }

    public static Scheduler createIoScheduler(ThreadFactory threadFactory) {
        if (threadFactory == null) {
            throw new NullPointerException("threadFactory == null");
        }
        return new CachedThreadScheduler(threadFactory);
    }
}

第5行的 “RxIoScheduler-“是子線程的前綴,如果調試日誌中有輸出這個信息,那就會看到這個前綴。

第12行使用這個ThreadFactory構建了一個CachedThreadScheduler,繼續跟進:

//第6段代碼
//rx.internal.schedulers.CachedThreadScheduler 只拷貝了相關核心代碼 
public final class CachedThreadScheduler extends Scheduler implements SchedulerLifecycle {

    private static final long KEEP_ALIVE_TIME = 60;
    private static final TimeUnit KEEP_ALIVE_UNIT = TimeUnit.SECONDS;
    final AtomicReference<CachedWorkerPool> pool;

    public CachedThreadScheduler(ThreadFactory threadFactory) {
        this.threadFactory = threadFactory;
        this.pool = new AtomicReference<CachedWorkerPool>(NONE);
        start();
    }

    @Override
    public void start() {
        CachedWorkerPool update =
            new CachedWorkerPool(threadFactory, KEEP_ALIVE_TIME, KEEP_ALIVE_UNIT);
        if (!pool.compareAndSet(NONE, update)) {
            update.shutdown();
        }
    }

    @Override
    public Worker createWorker() {
        return new EventLoopWorker(pool.get());
    }

    static final class EventLoopWorker extends Scheduler.Worker implements Action0 {
        private final CompositeSubscription innerSubscription = new CompositeSubscription();
        private final CachedWorkerPool pool;
        private final ThreadWorker threadWorker;
        final AtomicBoolean once;

        EventLoopWorker(CachedWorkerPool pool) {
            this.pool = pool;
            this.once = new AtomicBoolean();
            this.threadWorker = pool.get();
        }

        @Override
        public void unsubscribe() {
            if (once.compareAndSet(false, true)) {
                // unsubscribe should be idempotent, so only do this once

                // Release the worker _after_ the previous action (if any) has completed
                threadWorker.schedule(this);
            }
            innerSubscription.unsubscribe();
        }

        @Override
        public void call() {
            pool.release(threadWorker);
        }

        @Override
        public boolean isUnsubscribed() {
            return innerSubscription.isUnsubscribed();
        }

        @Override
        public Subscription schedule(Action0 action) {
            return schedule(action, 0, null);
        }

        @Override
        public Subscription schedule(final Action0 action, long delayTime, TimeUnit unit) {
            if (innerSubscription.isUnsubscribed()) {
                // don't schedule, we are unsubscribed
                return Subscriptions.unsubscribed();
            }

            ScheduledAction s = threadWorker.scheduleActual(new Action0() {
                @Override
                public void call() {
                    if (isUnsubscribed()) {
                        return;
                    }
                    action.call();
                }
            }, delayTime, unit);
            innerSubscription.add(s);
            s.addParent(innerSubscription);
            return s;
        }
    }

    static final class CachedWorkerPool {
        private final ThreadFactory threadFactory;
        private final long keepAliveTime;

        CachedWorkerPool(final ThreadFactory threadFactory, long keepAliveTime, TimeUnit unit) {
            this.threadFactory = threadFactory;
            this.keepAliveTime = unit != null ? unit.toNanos(keepAliveTime) : 0L;
            ...
            ...
        }
        ThreadWorker get() {
            if (allWorkers.isUnsubscribed()) {
                return SHUTDOWN_THREADWORKER;
            }
            while (!expiringWorkerQueue.isEmpty()) {
                ThreadWorker threadWorker = expiringWorkerQueue.poll();
                if (threadWorker != null) {
                    return threadWorker;
                }
            }

            // No cached worker found, so create a new one.
            ThreadWorker w = new ThreadWorker(threadFactory);
            allWorkers.add(w);
            return w;
        }
    }

    static final class ThreadWorker extends NewThreadWorker {
        private long expirationTime;

        ThreadWorker(ThreadFactory threadFactory) {
            super(threadFactory);
            this.expirationTime = 0L;
        }

        public long getExpirationTime() {
            return expirationTime;
        }

        public void setExpirationTime(long expirationTime) {
            this.expirationTime = expirationTime;
        }
    }

}

第9、10行分別給兩個成員變量賦值。

別忘了第2段代碼中的Worker是由SchedulercreateWorker()方法創建的,所以看一下第25行的createWorker()方法,pool.get()獲取到的是pool指定的泛型CachedWorkerPool,將它傳入EventLoopWorker的構造方法,在第38行調用了get()方法跳轉到第99行,之後在第111行用剛纔的threadFactory構造了ThreadWorker,於是在第121行進入父類NewThreadWorker的構造方法,該父類如下:

//第7段代碼
//rx.internal.schedulers.NewThreadWorker 只拷貝了相關核心代碼
public class NewThreadWorker extends Scheduler.Worker implements Subscription {
    private final ScheduledExecutorService executor;

    public NewThreadWorker(ThreadFactory threadFactory) {
        ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, threadFactory);
        // Java 7+: cancelled future tasks can be removed from the executor thus avoiding memory leak
        boolean cancelSupported = tryEnableCancelPolicy(exec);
        if (!cancelSupported && exec instanceof ScheduledThreadPoolExecutor) {
            registerExecutor((ScheduledThreadPoolExecutor)exec);
        }
        executor = exec;
    }

    public ScheduledAction scheduleActual(final Action0 action, long delayTime, TimeUnit unit) {
        Action0 decoratedAction = RxJavaHooks.onScheduledAction(action);
        ScheduledAction run = new ScheduledAction(decoratedAction);
        Future<?> f;
        if (delayTime <= 0) {
            f = executor.submit(run);
        } else {
            f = executor.schedule(run, delayTime, unit);
        }
        run.add(f);

        return run;
    }
}

第7行使用Executors創建了一個線程池,傳入了兩個參數:核心線程數1、之前分析的帶有前綴“RxIoScheduler-“的ThreadFactory。最大線程數爲Integer.MAX_VALUE,非核心線程保留10ms。

第2段代碼的Worker會調用schedule方法,所以再回到第6段代碼的68行,之後在第74行調用了ThreadWorkerscheduleActual()方法,於是跳轉到第7段代碼的第16行。第17行對action進行了包裝,第18行將包裝後的action轉換成ScheduledAction對象,這是一個Runnable對象,所以第21行可以將它作爲executor.submit()方法的參數,這個executor就是剛纔創建的線程池。

之後線程池將會新開線程,並調用ScheduledActionrun()方法,繼續跟進:

//第8段代碼
//rx.internal.schedulers.ScheduledAction 只拷貝了相關核心代碼
public final class ScheduledAction extends AtomicReference<Thread> implements Runnable, Subscription {
    final SubscriptionList cancel;
    final Action0 action;

    public ScheduledAction(Action0 action) {
        this.action = action;
        this.cancel = new SubscriptionList();
    }

    @Override
    public void run() {
        try {
            lazySet(Thread.currentThread());
            action.call();
        } catch (OnErrorNotImplementedException e) {
            signalError(new IllegalStateException("Exception thrown on Scheduler.Worker thread. Add `onError` handling.", e));
        } catch (Throwable e) {
            signalError(new IllegalStateException("Fatal Exception thrown on Scheduler.Worker thread.", e));
        } finally {
            unsubscribe();
        }
    }

}

第16行的action就是剛纔包裝後的decoratedAction,所以跳轉到第6段代碼的第76行,之後在第80行又回調call()方法,跳轉到第2段代碼的第20行,接着就是之前分析過的 “回調上游Observable的onSubscribe的call()方法”。

至此,第2段代碼就已經打通了,子線程也已經開始運行。

我們對subscribeOn()的總結再加以完善:

  1. 該方法返回了一個新的Observable
  2. 新的Observable收到訂閱回調後, 創建了一個核心線程數爲1,最大線程數爲Integer.MAX_VALUE的線程池,新線程名的前綴爲 “RxIoScheduler-“,之後的代碼將運行在新線程中,直到遇到線程切換。
  3. 通過層層回調,最終回調了上游ObservableonSubscribecall()方法。
  4. 新的Observable中的OnSubscribecall回調中新建的Subscriber接收到事件後,繼續將事件傳遞給下游的Subscriber
  5. 該方法改變的是上游回調call()方法執行時所處的線程,當使用多個 subscribeOn() 時,只有第一個subscribeOn() 決定事件發送時的線程。

observeOn()

現在我們看一下observeOn(AndroidSchedulers.mainThread())這行代碼實現的原理:

//第9段代碼
public final Observable<T> observeOn(Scheduler scheduler) {
    return observeOn(scheduler, RxRingBuffer.SIZE);
}

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

public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
        if (this instanceof ScalarSynchronousObservable) {
            return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler);
        }
        return lift(new OperatorObserveOn<T>(scheduler, delayError, bufferSize));
}

public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
        return create(new OnSubscribeLift<T, R>(onSubscribe, operator));
}

經過兩個方法的調用,在第14行出現了新的對象OperatorObserveOn,先不管它,繼續看主邏輯。

第18行又是我們熟悉的create()方法,不用多說,它的參數是個OnSubscribe接口對象,跟進OnSubscribeLift

//第10段代碼
public final class OnSubscribeLift<T, R> implements OnSubscribe<R> {

    final OnSubscribe<T> parent;

    final Operator<? extends R, ? super T> operator;

    public OnSubscribeLift(OnSubscribe<T> parent, Operator<? extends R, ? super T> operator) {
        this.parent = parent;
        this.operator = operator;
    }

    @Override
    public void call(Subscriber<? super R> o) {
        try {
            Subscriber<? super T> st = RxJavaHooks.onObservableLift(operator).call(o);
            try {
                st.onStart();
                parent.call(st);
            } catch (Throwable e) {
                Exceptions.throwIfFatal(e);
                st.onError(e);
            }
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            o.onError(e);
        }
    }
}

這個類代碼不多,比較簡單。第16行新建了一個Subscriber對象,緊接着又是熟悉的操作:調用這個新Subscriber對象的onStart()方法、回調上游OnSubscribecall()方法。

很明顯,這裏收到訂閱回調後沒有發生線程切換,也沒有其他多餘的操作。

那這個新的Subscriber對象接收到事件後,又發生了什麼呢?

根據第16行,我們要看第9段代碼第14行OperatorObserveOncall()方法來了解這個新的Subscriber對象了:

//第11段代碼
//rx.internal.operators.OperatorObserveOn 只拷貝了相關核心代碼
public final class OperatorObserveOn<T> implements Operator<T, T> {

    public OperatorObserveOn(Scheduler scheduler, boolean delayError, int bufferSize) {
        this.scheduler = scheduler;
        this.delayError = delayError;
        this.bufferSize = (bufferSize > 0) ? bufferSize : RxRingBuffer.SIZE;
    }

    @Override
    public Subscriber<? super T> call(Subscriber<? super T> child) {
        if (scheduler instanceof ImmediateScheduler) {
            // avoid overhead, execute directly
            return child;
        } else if (scheduler instanceof TrampolineScheduler) {
            // avoid overhead, execute directly
            return child;
        } else {
            ObserveOnSubscriber<T> parent = new ObserveOnSubscriber<T>(scheduler, child, delayError, bufferSize);
            parent.init();
            return parent;
        }
    }

    static final class ObserveOnSubscriber<T> extends Subscriber<T> implements Action0 {
        public ObserveOnSubscriber(Scheduler scheduler, Subscriber<? super T> child, boolean delayError, int bufferSize) {
            this.child = child;
            this.recursiveScheduler = scheduler.createWorker();
            this.delayError = delayError;
            ...
            ...
        }

        @Override
        public void onNext(final T t) {
            if (isUnsubscribed() || finished) {
                return;
            }
            if (!queue.offer(NotificationLite.next(t))) {
                onError(new MissingBackpressureException());
                return;
            }
            schedule();
        }

        @Override
        public void onCompleted() {
            if (isUnsubscribed() || finished) {
                return;
            }
            finished = true;
            schedule();
        }

        @Override
        public void onError(final Throwable e) {
            if (isUnsubscribed() || finished) {
                RxJavaHooks.onError(e);
                return;
            }
            error = e;
            finished = true;
            schedule();
        }

        protected void schedule() {
            if (counter.getAndIncrement() == 0) {
                recursiveScheduler.schedule(this);
            }
        }
    }
}

進入第12行的call()方法,因爲我們使用的是AndroidSchedulers.mainThread(),所以就直接到了第20行。這裏將ObserveOnSubscriber作爲Subscriber返回,所以再看這個對象的onNext()等方法就知道如何處理事件了。

第40行將當前接收到的事件保存進了隊列queue,先記住這點,後面就會用到了。

第44、53、64行都調用了schedule()這個方法。注意:onCompleted()onError方法中都將標誌位finished設爲了true

第69行調用了recursiveSchedulerschedule()方法,recursiveScheduler是在第20行跳到29行賦值的,我們需要找到AndroidSchedulers.mainThread()createWorker()方法,先找到AndroidSchedulers.mainThread()

//第12段代碼
//rx.android.schedulers.AndroidSchedulers 只拷貝了相關核心代碼
public final class AndroidSchedulers {
    private final Scheduler mainThreadScheduler;

    private AndroidSchedulers() {
        RxAndroidSchedulersHook hook = RxAndroidPlugins.getInstance().getSchedulersHook();

        Scheduler main = hook.getMainThreadScheduler();
        if (main != null) {
            mainThreadScheduler = main;
        } else {
            mainThreadScheduler = new LooperScheduler(Looper.getMainLooper());
        }
    }
}

第13行用主線程的Looper構建了LooperScheduler,繼續跟進:

//第13段代碼
//rx.android.schedulers.Scheduler 
class LooperScheduler extends Scheduler {
    private final Handler handler;

    LooperScheduler(Looper looper) {
        handler = new Handler(looper);
    }

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

    static class HandlerWorker extends Worker {

        @Override
        public Subscription schedule(final Action0 action) {
            return schedule(action, 0, TimeUnit.MILLISECONDS);
        }

        @Override
        public Subscription schedule(Action0 action, long delayTime, TimeUnit unit) {
            if (unsubscribed) {
                return Subscriptions.unsubscribed();
            }

            action = hook.onSchedule(action);

            ScheduledAction scheduledAction = new ScheduledAction(action, handler);

            Message message = Message.obtain(handler, scheduledAction);
            message.obj = this; // Used as token for unsubscription operation.

            handler.sendMessageDelayed(message, unit.toMillis(delayTime));

            if (unsubscribed) {
                handler.removeCallbacks(scheduledAction);
                return Subscriptions.unsubscribed();
            }

            return scheduledAction;
        }
    }

    static final class ScheduledAction implements Runnable, Subscription {
        ScheduledAction(Action0 action, Handler handler) {
            this.action = action;
            this.handler = handler;
        }

         @Override
         public void run() {
            try {
                action.call();
            } catch (Throwable e) {
              ...
            }
        }
    }
}

第12行又用主線程的Looper構建了HandlerWorker,所以只要看HandlerWorkerschedule()方法就行了。

第35行向主線程的消息隊列發送了一條消息,這條消息將被主線程的Looper取出,到時候第30行scheduledAction的回調run()方法就會在主線程執行了,這就實現了切換回主線程的目的

再看第53行,run()方法裏又回調了actioncall()方法,即第11段代碼第26行類ObserveOnSubscriber所實現的方法,如下:

@Override
public void call() {
    long missed = 1L;
    long currentEmission = emitted;
    final Queue<Object> q = this.queue;
    final Subscriber<? super T> localChild = this.child;
    for (;;) {
        long requestAmount = requested.get();

        while (requestAmount != currentEmission) {
            boolean done = finished;
            Object v = q.poll();
            boolean empty = v == null;

            if (checkTerminated(done, empty, localChild, q)) {
                return;
            }

            if (empty) {
                break;
            }

            localChild.onNext(NotificationLite.<T>getValue(v));

            currentEmission++;
            if (currentEmission == limit) {
                requestAmount = BackpressureUtils.produced(requested, currentEmission);
                request(currentEmission);
                currentEmission = 0L;
            }
        }

        if (requestAmount == currentEmission) {
            if (checkTerminated(finished, q.isEmpty(), localChild, q)) {
                return;
            }
        }

        emitted = currentEmission;
        missed = counter.addAndGet(-missed);
        if (missed == 0L) {
            break;
        }
    }
}

第6行的localChild就是下游Subscriber,這從第11代碼中不難發現。

第12行取出了之前保存在隊列queue中的事件,第23行調用了下游SubscriberonNext()方法,事件繼續向下傳遞,而這一切都發生在主線程中。

至此,對observeOn()方法可以有如下總結:

  1. 該方法返回了一個新的Observable
  2. 新的Observable收到訂閱回調後,回調了上游ObservableonSubscribecall()方法。
  3. 新的Observable中的OnSubscribecall回調中新建的Subscriber接收到事件後,將事件包裝後發送到主線程的消息隊列。
  4. 在主線程中,事件繼續向下遊Subscriber傳遞。
  5. 該方法改變的是下游訂閱者方法執行時所處的線程,可以通過多次調用observeOn()方法,實現下游訂閱者在多個線程間切換執行。

線程調度總結

以上對兩種線程調度操作符都做了詳細的分析和總結,切換線程時一個利用線程池,一個利用主線程Looper消息機制。

再配合下面這幅流程圖食用,消化更佳~

這幅圖來自於扔物線給 Android 開發者的 RxJava 詳解,因爲這幅圖總結地很好,和本文分析的結論也是完全一致,所以就直接拿來用了。

這裏寫圖片描述

相信理解完本文內容,大家對RxJava 1.x應該有了較好的認識,當然它的其他實現原理也很值得我們再深入研究。

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