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 );
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章