In this tutorial, we’ll be discussing Subjects in RxJava. We won’t be covering the basics of RxJava. If you are new to RxJava, do read this tutorial before proceeding ahead.
在本教程中,我们将在RxJava要讨论的主题 。 我们不会介绍RxJava的基础知识。 如果您不熟悉RxJava,请先阅读本教程,然后再继续。
什么是主题? (What is a Subject?)
We know Observables and Observers. Observables emit data. Observers listen to those emissions by subscribing with the help of Subscribers.
我们知道可观察者和观察者。 可观察对象发出数据。 观察者通过在订户的帮助下进行订阅来收听这些辐射。
Subjects can emit and subscribe to the data. They have the implementations of Observables as well as Observers.
受试者可以发出并订阅数据。 它们具有Observables和Observers的实现。
A Subject has the same operators that an Observable has.
They can multicast too. This means all the Observers subscribed to it will receive the same emissions from the point of subscription.
This prevents doing duplicate operations for multiple subscribers.
主题具有与可观察对象相同的运算符。
他们也可以多播。 这意味着所有订阅的观察者将从订阅点接收相同的发射。
这样可以防止对多个订户进行重复操作。
Where is a Subject used?
在哪里使用主题?
Subjects are commonly used when you need to observe some data and then later can emit that data to other observers.
当您需要观察一些数据然后稍后可以将该数据发送给其他观察者时,通常使用主题。
Let’s look at an example with and without Subject. We’ll see how Subject saves us from redundant operations.
让我们看一个带有和不带有Subject的示例。 我们将看到Subject如何使我们免于冗余操作。
Observable<Integer> observable =
Observable.just(1, 2).subscribeOn(Schedulers.computation())
.map(val -> {
System.out.println("map operation. Squaring : " + val * val);
return val;
});
observable.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
System.out.println("first subscriber : " + integer);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
observable.subscribe(l ->
System.out.println("second subscriber :" + l));
We’ve subscribed two Observers. Let’s see what the output prints.
我们已订阅了两名观察员。 让我们看看输出显示了什么。
The map operation is computed each time for each observer.
每次为每个观察者计算地图操作。
By using Subject we can remove this redundancy as shown below:
通过使用Subject,我们可以删除此冗余,如下所示:
Observable<Integer> observable =
Observable.just(1, 2).subscribeOn(Schedulers.computation())
.map(val -> {
System.out.println("map operation. Squaring : " + val * val);
return val;
});
PublishSubject<Integer> pSubject = PublishSubject.create();
observable.subscribe(pSubject);
pSubject.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("First Subscriber");
}
@Override
public void onNext(Integer integer) {
System.out.println("onNext");
}
@Override
public void onError(Throwable e) {
System.out.println("onError");
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
});
pSubject.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("Second Subscriber");
}
@Override
public void onNext(Integer integer) {
System.out.println("onNext");
}
@Override
public void onError(Throwable e) {
System.out.println("onError");
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
});
PublishSubject
is a subclass of Subject
.
PublishSubject
是Subject
的子类。
The output is:
输出为:
So the map operation isn’t repeated for the second subscriber.
Thus the Subject multicasts to all of its subscribers. That means that the data would be emitted and computed just once.
因此,第二个订户不会重复执行映射操作。
因此,主题将多播到其所有订户。 这意味着数据将仅被发射和计算一次。
Let’s explain this with a metaphor.
让我们用一个隐喻来解释一下。
Case 1
You are watching a movie on Youtube. You call your friend and tell him to subscribe to that channel and watch it too. He opens his Youtube and starts the movie.
情况1
您正在YouTube上看电影。 您呼叫朋友并告诉他订阅该频道并观看。 他打开自己的Youtube并开始播放电影。
Case 2
You are watching a live cricket/football match. Your friend joins you after some time.
情况二
您正在看现场板球/足球比赛。 一段时间后,您的朋友加入了您。
In Case 1, you and your friend would be able to watch the full movie from the beginning.
In Case 2, the friend won’t be able to watch the match from the beginning.
在案例1中,您和您的朋友将从一开始就可以观看整部电影。
在案例2中,朋友从一开始就无法观看比赛。
- Case 1 = Cold Observables. All observers would get the emissions from the beginning. 情况1 =冷观测值。 所有观察员将从一开始就获得排放。
- Case 2 = Hot Observables. Every Observer would receive emissions only from the point when they subscribed. 情况2 =热观测值。 每个观察员仅在订阅时才接收排放。
主题是可观察的热点 (Subjects are Hot Observables)
Now that we’re clear about Hot Observables, let’s validate whether Subjects are Hot Observables or not with an example:
现在我们已经了解了热可观测对象,下面通过一个示例来验证主题是否为热可观测对象:
PublishSubject<Integer> pSubject = PublishSubject.create();
pSubject.onNext(0);
pSubject.subscribe(it -> {
System.out.println("Observer 1 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 1 onCompleted"), on1 -> System.out.println("Observer 1 onSubscribe"));
pSubject.onNext(1);
pSubject.onNext(2);
pSubject.subscribe(it -> {
System.out.println("Observer 2 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 2 onCompleted"), on1 -> System.out.println("Observer 2 onSubscribe"));
pSubject.onNext(3);
pSubject.subscribe(it -> {
System.out.println("Observer 3 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 3 onCompleted"), on1 -> System.out.println("Observer 3 onSubscribe"));
pSubject.onNext(4);
pSubject.onComplete();
The output printed in the console is:
控制台中输出的输出为:
As you can see the Observer 2 and Observer 3 don’t get the values emitted by the Subject before the point of subscription.
如您所见,观察者2和观察者3在订阅点之前未获得主题发出的值。
学科类型 (Types of Subject)
Following are the different types of Subjects. Each works differently.
以下是不同类型的主题。 每个工作原理都不同。
- PublishSubject 发布主题
- BehaviorSubject 行为主体
- AsyncSubject 异步主题
- ReplaySubject 重播主题
- UnicastSubject 单播主题
- SingleSubject 单科
发布主题 (PublishSubject)
This emits all the items at the point of subscription. This is the most basic form of Subject and we’ve implemented it above.
这将在订阅时发出所有项目。 这是Subject的最基本形式,我们已经在上面实现了。
行为主体 (BehaviorSubject)
An observer, when subscribed to the BehaviorSubject, would get the last emitted item before it subscribed and all subsequent items.
观察者在订阅BehaviorSubject时,将获得订阅之前的最后一个发射项目以及所有后续项目。
Example:
例:
BehaviorSubject<Integer> behaviorSubject = BehaviorSubject.create();
behaviorSubject.onNext(0);
behaviorSubject.subscribe(it -> {
System.out.println("Observer 1 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 1 onCompleted"), on1 -> System.out.println("Observer 1 onSubscribe"));
behaviorSubject.onNext(1);
behaviorSubject.onNext(2);
behaviorSubject.subscribe(it -> {
System.out.println("Observer 2 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 2 onCompleted"), on1 -> System.out.println("Observer 2 onSubscribe"));
behaviorSubject.onNext(3);
behaviorSubject.subscribe(it -> {
System.out.println("Observer 3 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 3 onCompleted"), on1 -> System.out.println("Observer 3 onSubscribe"));
behaviorSubject.onNext(4);
behaviorSubject.onComplete();
Output:
输出:
异步主题 (AsyncSubject)
Of all the emissions, AsyncSubject would emit only the last item. That too only when onComplete()
gets called.
在所有发射中,AsyncSubject仅发射最后一个项目。 仅在调用onComplete()
时也是如此。
Example:
例:
AsyncSubject<Integer> asyncSubject = AsyncSubject.create();
asyncSubject.onNext(0);
asyncSubject.subscribe(it -> {
System.out.println("Observer 1 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 1 onCompleted"), on1 -> System.out.println("Observer 1 onSubscribe"));
asyncSubject.onNext(1);
asyncSubject.onNext(2);
asyncSubject.onComplete();
asyncSubject.subscribe(it -> {
System.out.println("Observer 2 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 2 onCompleted"), on1 -> System.out.println("Observer 2 onSubscribe"));
asyncSubject.onNext(3);
Output:
输出:
As you can see if the onComplete was called before the second observer subscribed, still that observer would get the last emitted value, even if it was before it subscribed.
如您所见,如果onComplete在第二个观察者订阅之前被调用,则即使该观察者在订阅之前,该观察者仍将获得最后发出的值。
重播主题 (ReplaySubject)
As the name says, when an observer subscribes to a ReplaySubject, it would get all the items from the beginning.
顾名思义,当观察者订阅ReplaySubject时,它将从头开始获取所有项目。
Example:
例:
ReplaySubject<Integer> replaySubject = ReplaySubject.create();
replaySubject.onNext(0);
replaySubject.subscribe(it -> {
System.out.println("Observer 1 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 1 onCompleted"), on1 -> System.out.println("Observer 1 onSubscribe"));
replaySubject.onNext(1);
replaySubject.onNext(2);
replaySubject.subscribe(it -> {
System.out.println("Observer 2 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 2 onCompleted"), on1 -> System.out.println("Observer 2 onSubscribe"));
replaySubject.onNext(3);
replaySubject.subscribe(it -> {
System.out.println("Observer 3 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 3 onCompleted"), on1 -> System.out.println("Observer 3 onSubscribe"));
replaySubject.onNext(4);
replaySubject.onComplete();
Output:
输出:
单播主题 (UnicastSubject)
A UnicastSubject can have a single observer only. Otherwise it will throw an error. Also it emits all the values from the beginning.
UnicastSubject只能有一个观察者。 否则会抛出错误。 它还从一开始就发出所有值。
Example:
例:
UnicastSubject<Integer> unicastSubject = UnicastSubject.create();
unicastSubject.onNext(0);
unicastSubject.subscribe(it -> {
System.out.println("Observer 1 onNext: " + it);
}, (Throwable onError) -> System.out.println("Observer 1 onError"), () -> System.out.println("Observer 1 onCompleted"), on1 -> System.out.println("Observer 1 onSubscribe"));
unicastSubject.onNext(1);
unicastSubject.onNext(2);
unicastSubject.subscribe(it -> {
System.out.println("Observer 2 onNext: " + it);
}, (Throwable onError) ->
System.out.println("Observer 2 onError"), () -> System.out.println("Observer 2 onCompleted"), on1 -> System.out.println("Observer 2 onSubscribe"));
unicastSubject.onNext(3);
Output:
输出:
单科 (SingleSubject)
Last but not the least, a SingleSubject can emit only one item to all its observers. Multiple observers can subscribe to it. It can subscribe to multiple SingleObservables.
最后但并非最不重要的一点是,SingleSubject只能向其所有观察者发射一项。 多个观察者可以订阅它。 它可以订阅多个SingleObservables。
Example:
例:
Single<Integer> singleObservable = Single.just(1)
.subscribeOn(Schedulers.computation());
Single<Integer> singleObservableTwo = Single.just(2)
.subscribeOn(Schedulers.computation());
SingleSubject<Integer> singleSubject = SingleSubject.create();
singleObservable.subscribe(singleSubject);
singleObservableTwo.subscribe(singleSubject);
singleSubject.subscribe(integer -> System.out.println("Observer 1 onNext: " + integer), error -> System.out.println("onError"));
singleSubject.subscribe(integer -> System.out.println("Observer 2 onNext: " + integer), error -> System.out.println("onError"));
Output:
输出:
PS: We can set transformation operators on the Subject in the same way as we do on Observables:
PS:我们可以像在Observables上一样,在Subject上设置转换运算符:
PublishSubject<Integer> publishSubject = PublishSubject.create();
Observable<Integer> observable = publishSubject.filter(it-> it%2==0);
publishSubject.onNext(0);
observable.subscribe(it -> {
System.out.println("Observer 1 onNext: " + it);
}, (Throwable onError) -> {
}, () -> System.out.println("Observer 1 onCompleted"), on1 -> System.out.println("Observer 1 onSubscribe"));
publishSubject.onNext(1);
publishSubject.onNext(2);
Only 2 would be printed.
仅打印2张。
And that sums up RxJava Subject for us.
这就为我们总结了RxJava Subject。