目錄
【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方法來強制發射數據。