「RxJava進階」基於原始碼的上游(Observable)事件產生流程分析

anAngryAnt發表於2018-03-22

既然是進階知識,假定你已經擁有RxJava相關的使用經驗,所以我就不多逼逼它的好了,本文將結合原始碼,來分析一個Observable是如何發出事件的

Context

  • rxjava:1.0.16
  • 本文貼出的rxjava原始碼都是精簡過的,旨在簡潔地表達原始碼意圖

1. 概念準備,何為上/下游事件?

上/下游事件,是在Rx中用來描述事件所處位置的,這其實是一個相對的概念。我使用一段示例程式碼來解釋這個概念。

Observable
    .just("hello")
    .map(s->s+=‘OK’)
    .subscribe(Action1->{...})
複製程式碼

按照我們上面程式碼來分析,justmap的上面,而Action1map的下面,資料傳遞流程是這樣的:just->map->Action1,所以對於map來說,just是它的上游,而Action1是它的下游。在Rx中,事件是從上游流向下游的。


2. 上游事件是如何產生的?

「RxJava進階」基於原始碼的上游(Observable)事件產生流程分析
我將選擇一個較簡單的Create Operator--just來作為例子。

Observable
    .just("hello")
    .subscribe(Action1->{...})
複製程式碼

2.1 精簡過後的just(T t)原始碼

public static <T> Observable<T> just(final T value) {
    return ScalarSynchronousObservable.create(value);
}

....

// 現階段先不管Scalar到底是個啥,我們知道
// SynchronousObservable是一個同步的Observable就夠了

-- ScalarSynchronousObservable.java
public static <T> ScalarSynchronousObservable<T> create(T t) {
    return new ScalarSynchronousObservable<T>(t);
}

protected ScalarSynchronousObservable(final T t) {
    super(new JustOnSubscribe<T>(t));
    this.t = t;
}

-- Observable.java
public class Observable<T> {

    final OnSubscribe<T> onSubscribe;

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

複製程式碼

結論1: just()呼叫完之後,返回的是一個新的Observable,而這個ObservableonSubcribe也是新的,他叫JustOnSubscribe,然而這個t,就是我們傳進來的"hello"。 目前為止,我們已經有一個Observable,和兩個onSubcriber了,一個是ScalarSynchronousObservable生成的,一個是我們傳入subscribe()中的。

在剛剛的分析中,我們並沒有看到觸發Subscriber的邏輯,我們剛剛猜想,是subscribe方法促使“Hello”傳遞到Action1的,那麼我們來看看Observable.subscribe方法的具體實現。

2.2 Observable.subscribe()


---Observable.java
public final Subscription subscribe(final Action1<? super T> onNext) {
   
    Action1<Throwable> onError = InternalObservableUtils.ERROR_NOT_IMPLEMENTED;
    Action0 onCompleted = Actions.empty();
    // 如果在subscribe中傳遞的是Action,而不是subscriber
    // 那麼Observable內部會將Action組裝成一個Subscriber(其實Subscriber內部也是由Action通過組合的方式實現的,有點像代理模式)
    return subscribe(new ActionSubscriber<T>(onNext,onError,onCompleted));
}

public final Subscription subscribe(Subscriber<? super T> subscriber) {
    // 因為just()操作符會生成一個新的Observable
    // 所以我們在鏈式呼叫中執行的subscribe方法
    // 也就是新Observable的方法
    // 要記得新Observable.onSubcribe物件也是新的,它叫JustOnSubscribe
    return Observable.subscribe(subscriber, this);
}

static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
     
        subscriber.onStart();

        try {
            //這麼一來,justOnSubscribe.call()裡到底執行了什麼就很關鍵了
            justOnSubscribe.call(subscriber)
            //原始碼:RxJavaHooks.onObservableStart(observable,observable.onSubscribe).call(subscriber);
            
            // Subscriber是Observer的同時也是Subscription
            // 直接返回以便進行unsubscribed()操作
            return subscriber;
            //原始碼:RxJavaHooks.onObservableReturn(subscriber)
        } catch (Throwable e) {
            // throw exceptions 
        }
        return Subscriptions.unsubscribed();
    }
}


--- ScalarSynchronousObservable.java
static final class JustOnSubscribe<T> implements OnSubscribe<T> {
    final T value;

    JustOnSubscribe(T value) {
        this.value = value;
    }

    @Override
    public void call(Subscriber<? super T> s) {
        s.setProducer(createProducer(s, value));
    }
}

static <T> Producer createProducer(Subscriber<? super T> s, T v){
    // 這個常量我們先不管,它預設為false
    if (STRONG_MODE) {
        return new SingleProducer<T>(s, v);
    }
    //我們預設認為返回WeakSingleProducer即可
    return new WeakSingleProducer<T>(s, v);
}

複製程式碼

我在上面程式碼寫了一些註釋,對一些較為關鍵的點做了分析。 現在我們再來昇華一下,做一個Observable.subscribe()呼叫流程的最後結論:

  • Observable.subscribe()方法中,呼叫了OnSubscribe.call()
  • 因為在just()中,生成了一個新的Observable物件,並且Observable.onSubscribeJustOnSubscribe
  • justOnSubscribe.call(subscriber)subscriber,是RxJava根據我們在subscribe()傳遞的Action1生成的ActionSubscriber。
  • justOnSubscribe.call()中,生成了一個WeakSingleProducer,並且為ActionSubscriber設定了WeakSingleProducer

接下來,我們要把目光轉移到,Subscriber.setProducer()WeakSingleProducer這個類上了.

2.3 subscriber.setProducer

--- Subscriber.java
public void setProducer(Producer p) {
    // 對於本例,省略一些背壓和併發控制的邏輯程式碼
    // 以下為精簡後的原始碼
    producer.request(Long.MAX_VALUE);
}
複製程式碼

2.4 weakSingleProducer.request

static final class WeakSingleProducer<T> implements Producer {
    final Subscriber<? super T> actual;
    final T value;
    boolean once;

    public WeakSingleProducer(Subscriber<? super T> actual, T value) {
        this.actual = actual;
        this.value = value;
    }

    @Override
    public void request(long n) {
        if (once) {
            return;
        }
        if (n < 0L) {
            throw new IllegalStateException("n >= required but it was " + n);
        }
        if (n == 0L) {
            return;
        }
        once = true;
        Subscriber<? super T> a = actual;
        if (a.isUnsubscribed()) {
            return;
        }
        T v = value;
        try {
            a.onNext(v);
        } catch (Throwable e) {
            Exceptions.throwOrReport(e, a, v);
            return;
        }

        if (a.isUnsubscribed()) {
            return;
        }
        a.onCompleted();
    }
}
複製程式碼

「RxJava進階」基於原始碼的上游(Observable)事件產生流程分析
我們可以在WeakSingleProducer.request中很清晰的看到Subscriber的回撥方法的執行。我們的“Hello”字串也是在這裡傳遞到下游的Action1中的。 所以,我們是時候開始總結一波了!

2.5 完整的Observable事件產生流程

示例程式碼回顧:

Observable
    .just("hello")
    .map(s->s+=‘OK’)
    .subscribe(Action1->{...})
複製程式碼
  • 所以,對以上簡單的Rx程式碼,是如何產生事件的分析結論是:

    • just()函式會建立一個新的Observable,並且這個Observable.OnSubscribe會被設定一個JustOnSubscribe
    • Observable.subcribe()方法中,呼叫了JustOnSubscribe.call()
    • JustOnSubscribe.call()中,生成Producer用於處理下游最終資料的分發
  • 具體流程圖如下:

「RxJava進階」基於原始碼的上游(Observable)事件產生流程分析

2.6 廢話

其實,通過這次的分析得到的結論,我們可以做很多的猜想:

  • map,flatMap這樣的變換操作符的變換(Lift)流程是咋樣的呢?是否也是通過包裝Observable來達到的呢?
  • Schedular的排程流程是咋樣的呢?是否也是通過包裝Observable來達到的呢?

不久的將來,我也會通過原始碼來冷靜分析一波

相關文章