RxJava是如何實現訂閱關係的?

仙花鬥影發表於2019-03-06

什麼是RxJava

說到RxJava,就必須說到ReactiveX,它是一個程式設計模型,目標是提供一致的程式設計介面,幫助開發者更方便的處理非同步資料流,RxJava只是它的Java語言實現方式,還有諸如RxJS、Rx.NET等其他語言的版本。

用過RxJava的都知道它實現起來程式碼簡潔幹練,使用鏈式呼叫方式可以將一系列複雜的操作用僅用一段程式碼就能串起來。但這對於初次接觸它的人來說往往感覺可讀性很差,很難理解其中的奧祕,這篇文章主要介紹Rxjava最簡單的操作方式,並解析其中的原始碼。

RxJava的觀察者模式

RxJava最核心的思想就是觀察者模式。軟體開發過程中,經常就需要去後臺請求一串資料,請求到結果後將資料展示在頁面上,這時候如果用觀察者模式開發,就可以定義一個被觀察者,用來作資料請求,然後定義一個觀察者,用來處理介面展示,然後觀察者訂閱被觀察者。

等被觀察者請求的資料完成後,就通知觀察者資料已經完成可以介面更新了。RxJava就是通過這樣的方式來實現的。

RxJava的實現方式

舉一個很簡單的例子,假設我們要在後臺連續建立五個字串hello world,然後再通過前臺列印出來(為了描述更形象,後臺不是僅僅是在被觀察者中實現,沒有開執行緒處理),可以通過以下程式碼實現:

  1. 建立觀察者物件Observer,實現onSubscribe(), onNext(),onComplete(),onError();

  2. 建立被觀察者物件ObservableOnSubscribe,這裡使用了lumbda的寫法,引數e可以理解為就是Observer的物件,這個方法體裡面可以實現任何操作,然後拿到引數e將操作的結果通過onNext()通知給觀察者Observer;

  3. 呼叫訂閱方法subscribe,這個方法被執行後,被觀察者物件的操作就開始被執行。

Observable.create((ObservableOnSubscribe<String>) e ->
            for (int i = 0; i < 5; i++) {
                e.onNext("hello world " + i);
            }
            e.onComplete();
        ).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String o) {
                System.out.println("onNext" + o);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
                System.out.println("onComplete");
            }
        });
複製程式碼

執行結果:

onNexthello world 0
onNexthello world 1
onNexthello world 2
onNexthello world 3
onNexthello world 4
onComplete
複製程式碼

RxJava的實現原理

1. Observable的建立過程。

我們來看下Observable.create的原始碼,它將上面通過匿名類實現的ObservableOnSubscribe物件作為ObservableCreate的建構函式引數又建立了ObservableCreate物件。

public abstract class Observable<T> implements ObservableSource<T> {
    ...
    public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
          ObjectHelper.requireNonNull(source, "source is null");
          return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }
    ...
}
複製程式碼

ObservableCreate類很簡單,裡面只包含了ObservableOnSubscribe這個成員變數,就是通過上面的create函式傳進來的。

public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;
    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }
    ...
}    
複製程式碼

建立完ObservableCreate物件後,再呼叫RxJavaPlugins的靜態方法onAssembly,前者作為後者的引數傳入,onAssembly方法中還有一個apply的操作,這個我們目前還沒有用到,可以先忽略,所以這個方法就是將傳入的ObservableCreate物件直接返回。

public final class RxJavaPlugins {
  ...
  /**
   * 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> Observable<T> onAssembly(@NonNull Observable<T> source) {
      Function<? super Observable, ? extends Observable> f = onObservableAssembly;
      if (f != null) {
          return apply(f, source);
      }
      return source;
  }
  ...
}  
複製程式碼

2. Observer的建立過程:通過上個步驟返回的ObservableCreate物件再呼叫subscribe方法,我們直接建立了一個Observer匿名內部類作為引數傳入subscribe()方法,Observer就是我們定義的觀察者,內部實現了onNext,onComplete和onError方法。

3. 訂閱的流程。

接著我們重點分析subscribe的內部實現,由於ObservableCreate是Observable的子類,該方法首先是呼叫了父類Observable的subscribe方法,然後呼叫子類也就是ObservableCreate的subscribeActual方法。

這裡就使用了設計模式中的模板模式,在父類中定義了方法模板subscribe,再通過subscribeActual讓子類各自去實現。

public abstract class Observable<T> implements ObservableSource<T> {
  ...
  @Override
  public final void subscribe(Observer<? super T> observer) {
      ObjectHelper.requireNonNull(observer, "observer is null");
      try {
          observer = RxJavaPlugins.onSubscribe(this, observer);
          ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
          subscribeActual(observer);
      } catch (NullPointerException e) { // NOPMD
          throw e;
      } catch (Throwable e) {
          ...
      }
  }
  ...
}  
複製程式碼
public final class ObservableCreate<T> extends Observable<T> {
  ...
  @Override
  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);
      }
  }
  ...
}
複製程式碼

subscribeActual方法中建立了CreateEmitter例項parent,CreateEmitter是對Observer再作一層封裝,通過isDisposed方法判斷訂閱狀態是否已銷燬,只要沒被銷燬才會呼叫到我們定義的onNext等觀察者方法,通過parent呼叫的onNext、onError等方法內部就是拿到observer再呼叫對應的onNext、onError。

接著就是真正開始執行被觀察者的操作了,source.subscribe(parent)就是呼叫了我們在RxJava的實現方式中第二步建立的ObservableOnSubscribe物件了,即開始執行了for迴圈列印hello world的流程了。

static final class CreateEmitter<T>
    extends AtomicReference<Disposable>
    implements ObservableEmitter<T>, Disposable {

    final Observer<? super T> observer;

    CreateEmitter(Observer<? super T> observer) {
        this.observer = observer;
    }

    @Override
    public void onNext(T t) {
        if (t == null) {
            onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
            return;
        }
        if (!isDisposed()) {
            observer.onNext(t);
        }
    }
    ...
}
複製程式碼

相關文章