RxJava中常見的幾種Subject

RxJava是什麼?
原文是這樣描述的:

RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-based programs by using observable sequences.

翻譯過來就是一個在 Java VM 上使用可觀測的序列來組成異步的、基於事件的程序的庫。
它是觀察者模式的一個變種,既然是基於事件的,當然EventBus的東東它都可以實現。

下面就來說說幾種常用的Subject(既是觀察者又是被觀察對象)
從下圖可以看出它的子類有PublishSubject、BehaviorSubject、ReplaySubject、AsyncSubject、SerializedSubject。


這裏寫圖片描述


PublishSubject

Subject that, once an Observer has subscribed, emits all subsequently observed items to the subscriber.

PublishSubject算是RxJava中最常用的Subject,一旦一個觀察者訂閱了該Subject,它會發送所有數據給訂閱者。
什麼意思?看圖就明白了。

這裏寫圖片描述

也就是說訂閱者只會接受訂閱之後的來自PublishSubject發射的數據。

Example Code


PublishSubject<Object> subject = PublishSubject.create();

  // observer1 will receive all onNext and onCompleted events
  subject.subscribe(observer1);
  subject.onNext("one");
  subject.onNext("two");

  // observer2 will only receive "three" and onCompleted
  subject.subscribe(observer2);
  subject.onNext("three");
  subject.onCompleted();

那麼有人就會疑問?有沒有一種Subject能接受訂閱之前的數據呢?答案是有且不止一個,個人感覺使用場景最多的是BehaviorSubject


BehaviorSubject

官方是這樣描述:

Subject that emits the most recent item it has observed and all subsequent observed items to each subscribed Observer.

大意是BehaviorSubject會發送離訂閱最近的上一個值,沒有上一個值的時候會發送默認值(如果有的話)

這裏寫圖片描述

Example Code

// observer will receive all events.
  BehaviorSubject<Object> subject = BehaviorSubject.create("default");
  subject.subscribe(observer);
  subject.onNext("one");
  subject.onNext("two");
  subject.onNext("three");

  // observer will receive the "one", "two" and "three" events, but not "zero"
  BehaviorSubject<Object> subject = BehaviorSubject.create("default");
  subject.onNext("zero");
  subject.onNext("one");
  subject.subscribe(observer);
  subject.onNext("two");
  subject.onNext("three");

  // observer will receive only onCompleted
  BehaviorSubject<Object> subject = BehaviorSubject.create("default");
  subject.onNext("zero");
  subject.onNext("one");
  subject.onCompleted();
  subject.subscribe(observer);

  // observer will receive only onError
  BehaviorSubject<Object> subject = BehaviorSubject.create("default");
  subject.onNext("zero");
  subject.onNext("one");
  subject.onError(new RuntimeException("error"));
  subject.subscribe(observer);

使用BehaviorSubject的一種常見場景


ReplaySubject

Subject that buffers all items it observes and replays them to any Observer that subscribes.

該Subject會緩存所有的發射數據,無論觀察者何時訂閱,Subject都會將所有內容發送給訂閱者。

這裏寫圖片描述

Example Code

  ReplaySubject<Object> subject = ReplaySubject.create();
  subject.onNext("one");
  subject.onNext("two");
  subject.onNext("three");
  subject.onCompleted();

  // both of the following will get the onNext/onCompleted calls from above
  subject.subscribe(observer1);
  subject.subscribe(observer2);

AsyncSubject

Subject that publishes only the last item observed to each Observer once the source Observable has completed. The item is cached and published to any Observers which subscribe after the source has completed. If the source emitted no items, AsyncSubject completes without emitting anything. If the source terminated in an error, current and future subscribers will receive only the error.

概括的講就是使用AsyncSubject無論發送多少個數據事件,觀察者永遠只能接受到最後一個數據(完成事件必須調用)。如果發送數據過程中出現錯誤,觀察者僅僅接受到錯誤信息。

這裏寫圖片描述

Example Code

// observer will receive no onNext events because the subject.onCompleted() isn't called.
  AsyncSubject<Object> subject = AsyncSubject.create();
  subject.subscribe(observer);
  subject.onNext("one");
  subject.onNext("two");
  subject.onNext("three");

  // observer will receive "three" as the only onNext event.
  AsyncSubject<Object> subject = AsyncSubject.create();
  subject.subscribe(observer);
  subject.onNext("one");
  subject.onNext("two");
  subject.onNext("three");
  subject.onCompleted();

SerializedSubject

Wraps a Subject so that it is safe to call its various on methods from different threads.

如果你把 Subject 當作一個 Subscriber 使用,千萬要注意不要從多個線程中調用它的onNext(T)方法(包括其它的on系列方法),這可能導致同時非序列調用,這會違反Observable協議,給Subject的結果增加了不確定性。

要避免此類問題,你可以將 Subject 轉換爲一個 SerializedSubject

Example Code

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