適應RxJava2思維習慣

RxJava有幾個重要關鍵字,即函數響應式編程,觀察者模式,事件發射,消費等等。以下這段話摘自其他文章Android 響應式編程 RxJava2 完全解析。鳴謝作者。

響應式編程的組成爲Observable/Operator/Subscriber,RxJava在響應式編程中的基本流程>如下:
這個流程,可以簡單的理解爲:Observable -> Operator1 -> Operator2 -> Operator3 -> Subscriber

  1. Observable發出一系列事件,他是事件的產生者;
  2. Subscriber負責處理事件,他是事件的消費者;
  3. Operator是對Observable發出的事件進行修改和變換;
  4. 若事件從產生到消費不需要其他處理,則可以省略掉中間的Operator,從而流程變爲 Obsevable -> Subscriber;
  5. Subscriber通常在主線程執行,所以原則上不要去處理太多的事務,而這些複雜的處理則交給Operator;

假如中間沒有Operator,流程只有Observable到Subscriber,那麼畫UML類圖,跟蹤源碼,來看函數執行順序。
RxJava部分UML類圖

Observable.create(new ObservableOnSubscribe<IDAL>() {
    @Override
    public void subscribe(ObservableEmitter<IDAL> emitter) throws Exception {
        IDAL idal;
        try {
            idal = NeptuneLiteUser.getInstance().getDal(application);
        } catch (Exception e) {
            LogUtil.e(e);
            throw e;
        }
        if (!emitter.isDisposed()) {
            emitter.onNext(idal);
            emitter.onComplete();
        }
    }
}).subscribe(new Observer<Boolean>() {
    @Override
    public void onSubscribe(Disposable d) {
        mCompositeDisposable.add(d);
    }

    @Override
    public void onNext(Boolean aBoolean) {
        //nothing
        if (aBoolean) {
            initParamService();
        }
    }

    @Override
    public void onError(Throwable e) {
        //nothing
    }

    @Override
    public void onComplete() {
        //nothing
    }
});

調用Observable接口的靜態方法create創建了一個ObservableCreate被觀察者,

RxJavaPlugins.onAssembly(new ObservableCreate(new ObservableOnSubscribe<IDAL>(){})     )

然後通過Observable的subscribe方法將被觀察者ObservableCreate和新創建出來的觀察者new Observer綁定起來,前者傳遞給後者消費。
話分兩頭,一頭是RxJavaPlugins.onAssembly, 另一頭是Observable的subscribe函數。

RJavaPlugins.onAssembly內部調用了靜態成員變量onObservableAssembly的apply函數,經過轉換,返回的應該還是new ObservableCreate(new ObservableOnSubscribe(){}) 這個Observable對象。

另一頭Observable的subscribe函數只有兩行關鍵代碼,

observer = RxJavaPlugins.onSubscribe(this, observer);
subscribeActual(observer);

RxJavaPlugins.onSubscribe函數內部調用的也是一個轉換函數,但是形式與RxJavaPlugins.onAssembly內部調用的不太一樣。
subscribeActual是一個Observable的抽象方法,最終會調用到子類ObservableCreate的subscribeActual方法,在分析這個具體的subscribeActual函數做的三件事之前,
我們看看ObservableCreate這個類的定義

public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }

它有一個成員變量叫source, 類型是ObservableOnSubscribe,這個成員變量通過構造函數賦值的。也就是通過Observable的靜態方法create創建被觀察者時傳入的那個匿名對象。
前面已經討論過

RxJavaPlugins.onAssembly(new ObservableCreate(new ObservableOnSubscribe<IDAL>(){})     )

來看看ObservableCreate的subscribeActual做了哪三件事

@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);
    }
}
  1. 把new出來然後傳進來的Observer對象包裝成CreateEmitter類,變量名爲parent
  2. 調用上述Observer的onSubscribe函數,參數是上述CreateEmitter對象parent
  3. 調用ObservableCreate的成員變量source(ObservableOnSubscribe類型)的subscribe函數,傳入上述parent變量

所以在不使用操作符和線程切換,只創建被觀察者和觀察者,並且相互綁定,函數的執行順序是這樣的:

  1. 執行Observer的onSubscribe函數,這個方法是程序員自己寫的。
@Override
    public void onSubscribe(Disposable d) {
        mCompositeDisposable.add(d);
    }

這裏的Disposable形參d其實是CreateEmitter對象,CreateEmitter實現了Disposable接口。
2. 執行ObservableOnSubscribe的subscribe函數

@Override
    public void subscribe(ObservableEmitter<IDAL> emitter) throws Exception {
        IDAL idal;
        try {
            idal = NeptuneLiteUser.getInstance().getDal(application);
        } catch (Exception e) {
            LogUtil.e(e);
            throw e;
        }
        if (!emitter.isDisposed()) {
            emitter.onNext(idal);
            emitter.onComplete();
        }
    }

這裏的ObservableEmitter形參 emitter其實也是CreateEmitter對象,CreateEmitter實現了ObservableEmitter接口。
在這個subscribe方法也是程序員自己寫的。具體到這個例子,先進行了一些初始化,然後調用了CreateEmitter的onNext和onComplete方法。
我們又要到CreateEmitter這個類中去看看這兩個方法的具體實現。這個是ObservableCreate的靜態內部類,實現了ObservableEmitter和Disposable兩個接口

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

    private static final long serialVersionUID = -3434801548987643227L;

    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);
        }
    }

@Override
public void onComplete() {
    if (!isDisposed()) {
        try {
            observer.onComplete();
        } finally {
            dispose();
        }
    }
}

CreateEmitter的onNext和onComplete方法其實轉交回Observer的onNext呢onComplete方法了,只是會先判空,再判斷dispose標記。這裏的Observer就是開始new出來的觀察者。這裏的dispose標記可以理解爲流的開關。

總結
在RxJava2的以下代碼基本結構中

Observable.create(new ObservableOnSubscribe<IDAL>() {
    @Override
    public void subscribe(ObservableEmitter<IDAL> emitter) throws Exception {//2
    }).subscribe(new Observer<Boolean>() {
    @Override
    public void onSubscribe(Disposable d) {//1
    }

    @Override
    public void onNext(Boolean aBoolean) {//3
    }

    @Override
    public void onError(Throwable e) {
    }

    @Override
    public void onComplete() {//4
    }
});

實際的執行順序是:

  1. 先執行Observer的OnSubscribe方法,理解爲”即將訂閱時,做某某事“
  2. 執行Observable內的ObservableOnSubscribe成員的subscribe方法,理解爲”此處訂閱”。程序員在此處結合實際業務邏輯,調用
    Observer的onNext、onError、onComplete的任意組合。onNext、onError、onComplete被統稱爲事件發射,也就不難理解subscribe函數的參數爲什麼叫做發射器。
  3. 根據第2步中程序員自己定義的事件發射順序,逐個執行(消費)掉那些事件。

例子中的subscribe方法中,先發射onNext,再發射onComplete,實際上是可以任意的。比如,for循環60次,每次執行某些邏輯後發射onNext,循環結束後發射onComplete,如果中途有異常或錯誤,發射onError。是不是似曾相識?思考一下app登錄頁面的短信驗證碼倒計時頁面。

注意:真正的短信驗證碼倒計時頁面不會使用這麼笨的方法來發射事件,因爲RxJava提供了豐富的操作符來簡化典型的使用場景,比如interval。這也是它收到追捧的原因之一。
本篇介紹的是創建Observable->創建Observer–>訂閱,這種簡單結構的源碼分析,下一篇,將拆解 創建Observable->操作符–>創建Observer–>訂閱結構的源碼。

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