【RxJava】- 連接操作符源碼分析

目錄

【RxJava】- 創建操作符源碼分析
【RxJava】- 變換操作符源碼分析
【RxJava】- 過濾操作符源碼分析
【RxJava】- 結合操作符源碼分析

Connect

讓一個可連接的Observable開始發射數據給訂閱者,可連接的Observable (connectable Observable)與普通的Observable差不多,不過它并不會在被訂閱時開始發射數據,而是直到使用了Connect操作符時才會開始。用這個方法,你可以等待所有的觀察者都訂閱了Observable之后再開始發射數據。

RxJava中connect是ConnectableObservable接口的一個方法,使用publish操作符可以將一個普通的Observable轉換為一個ConnectableObservable。

Observable.create(null).replay().connect();

實現類

ConnectConsumer

自己查看,很簡單,就幾行代碼。

調用 connect(cc)方法,返回disposable實例。

Replay

保證所有的觀察者收到相同的數據序列,即使它們在Observable開始發射數據之后才訂閱.

可連接的Observable (connectable Observable)與普通的Observable差不多,不過它并不會在被訂閱時開始發射數據,而是直到使用了Connect操作符時才會開始。用這種方法,你可以在任何時候讓一個Observable開始發射數據。

實現類

ObservableReplay

Replay還有其它實現類,請自己查看。這里講解replay()沒有傳入參數的實現。看一下創建過程,最終創建ObservableReplay實例傳入的參數如下:

  • source
    被觀察者
  • bufferFactory
    UnBoundedFactory實例
  • curr
    final AtomicReference<ReplayObserver<T>> curr = new AtomicReference<>();
  • onSubscribe
    ObservableSource<T> onSubscribe = new ReplaySource<>(curr, bufferFactory);
    

首先調用connect(Consumer<? super Disposable> connection)方法

返回初始化容量為16的UnboundedReplayBuffer數組

ReplayBuffer<T> buf = bufferFactory.call();

保存新創建的ReplayObserver對象

if (!current.compareAndSet(ps, u)){continue;}

調用accept方法

connection.accept(ps);

這里調用的是上面Connect中的ConnectConsumer類中的accept方法。

public void accept(Disposable t) {
    this.disposable = t;
}

調用被觀察者

if (doConnect) {
    source.subscribe(ps);
}

調用onNext(T t)

public void onNext(T t) {
    if (!done) {
        // 保存到數據
        buffer.next(t);
        replay();
    }
}

核心邏輯就在replay中,自己查看。

Publish

將普通的Observable轉換為可連接的Observable

ConnectableObservable observable = Observable.create((ObservableOnSubscribe<Integer>) emitter -> {
    ObservableEmitter<Integer> observableEmitter = emitter.serialize();
    try {
        // 序列化
        if (!emitter.isDisposed()) {
            for (int i = 1; i < 3; i++) {
                System.out.println("create operate--->emitter: "+i);
                if (1==i){
                    // ExceptionHelper.TERMINATED
                   //   observableEmitter.onError(new Throwable("error"));
                }else {
                    observableEmitter.onNext(i);
                }
            }
            observableEmitter.onComplete();
        }
    } catch (Exception e) {
        observableEmitter.onError(e);
    }
}).publish();
observable.subscribe(new Observer<Integer>() {...});
observable.connect();

observable.connect()不調用,是不會發射數據的。

實現類

ObservablePublish

看subscribeActual方法

protected void subscribeActual(Observer<? super T> observer) {
    ...
    InnerDisposable<T> inner = new InnerDisposable<>(observer, co
    observer.onSubscribe(inner);
    if (conn.add(inner)) {
        if (inner.isDisposed()) {
            conn.remove(inner);
        }
        return;
    }
    ...
}

conn.add(inner)為每一個訂閱者創建InnerDisposable對象,然后保存在PublishConnection中的一個數組中。

看connect方法

public void connect(Consumer<? super Disposable> connection) {
    ...
    if (doConnect) {
        source.subscribe(conn);
    }
}

調用被觀察者subscribe對象,然后可以在里面發射數據。

PublishConnection中的 onNext方法

public void onNext(T t) {
    for (InnerDisposable<T> inner : get()) {
        inner.downstream.onNext(t);
    }

調用每一個訂閱者的onNext方法,將數據發射給訂閱者。

RefCount

讓一個可連接的Observable行為像普通的Observable??蛇B接的Observable (connectable Observable)與普通的Observable差不多,不過它并不會在被訂閱時開始發射數據,而是直到使用了Connect操作符時才會開始。用這種方法,你可以在任何時候讓一個Observable開始發射數據。

Observable observable = Observable.create((ObservableOnSubscrib
    ObservableEmitter<Integer> observableEmitter = emitter.seri
    try {
        // 序列化
        if (!emitter.isDisposed()) {
            for (int i = 0; i < 4; i++) {
                System.out.println("create operate--->emitter: 
                if (1==i){
                    // ExceptionHelper.TERMINATED
                      observableEmitter.onError(new Throwable("
                }else {
                    observableEmitter.onNext(i);
                }
            }
            observableEmitter.onComplete();
        }
    } catch (Exception e) {
        observableEmitter.onError(e);
    }
}).publish().refCount(2);
observable.subscribe(...);
observable.subscribe(...);

實現類

ObservableRefCount

看一下subscribeActual方法

protected void subscribeActual(Observer<? super T> observer) {
    RefConnection conn;
    boolean connect = false;
    synchronized (this) {
        conn = connection;
        if (conn == null) {
            conn = new RefConnection(this);
            connection = conn;
        }
        long c = conn.subscriberCount;
        if (c == 0L && conn.timer != null) {
            conn.timer.dispose();
        }
        conn.subscriberCount = c + 1;
        if (!conn.connected && c + 1 == n) {
            connect = true;
            conn.connected = true;
        }
    }
    source.subscribe(new RefCountObserver<>(observer, this, conn));
    if (connect) {
        source.connect(conn);
    }
}

if (!conn.connected && c + 1 == n)當訂閱者的數量等于refCount方法傳入的數量時,表示可以連接,調用ObservablePublish中的connect方法。就與上面將Publish操作符調用connect方法作用相同。

當然你可以隨時調用connect方法來強制發射數據。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容