Exploring RxJava in Android — Different types of Subjects
This article is part of RxJava Introduction series. You can checkout the entire series here:
- RxJava Introduction and Operators for creating Observables
- RxJava Operators: Operators for Transforming Observables
- RxJava Operators: Operators for Filtering Observables
- RxJava Operators: Operators for Combining Observables
- RxJava Operators: Utility Operators
- RxJava Operators: Conditional and Boolean Operators
- RxJava Operators: Mathematical and Aggregate Operators
- RxJava: Different types of Observables
- RxJava: Different types of Subjects — You are here
What are Subjects?
A Subject extends an Observable and implements Observer at the same time. It acts as an Observable to clients and registers to multiple events taking place in the app. It acts as an Observer by broadcasting the event to multiple subscribers.
Some characteristics of Subjects
- Subjects can act as both an Observer and an Observable.
Example scenario: In the following example, we create an Observable which emits integers from 1 to 5. We create a subject, and use it to observe the changes to the Observable(In this scenario, the Subject is acting as an Observer). We will have two Observers to observe the changes in the Subject (In this scenario, the Subject is acting as an Observable).
Output:
subscriber one: 1
subscriber one: 2
subscriber one: 3
subscriber one: 4
subscriber one: 5
subscriber two: 1
subscriber two: 2
subscriber two: 3
subscriber two: 4
subscriber two: 5
- Subjects can multicast items to multiple child subscribers. Multicasting makes it possible to run expensive operations once and emit the results to multiple subscribers. This prevents doing duplicate operations for multiple subscribers.
Example scenario: In the following example, we create an Observable which emits integers from 1 to 5. Each integer is squared by itself using the map() operator before it is emitted. We will have two Observers to observe the Observable.
Without Subjects:
Output
Squaring 1 with itself
Squaring 1 with itself
subscriber one: 1
subscriber two: 1
Squaring 2 with itself
Squaring 2 with itself
subscriber one: 4
subscriber two: 4
Squaring 3 with itself
Squaring 3 with itself
subscriber one: 9
subscriber two: 9
You will note that for each Observer, the map() operation is being carried out twice. So if we had 10 Observers, the map() operation would be carried out 10 times before the integer is emitted.
Now let’s test the same scenario using Subjects:
Output
Squaring 1 with itself
Squaring 2 with itself
Squaring 3 with itself
Squaring 4 with itself
Squaring 5 with itself
subscriber one: 1
subscriber one: 4
subscriber one: 9
subscriber one: 16
subscriber one: 25
subscriber two: 1
subscriber two: 4
subscriber two: 9
subscriber two: 16
subscriber two: 25
You can see from the output that the map() operation only takes place once, even if there are 2 subscribers. So if we have 10 subscribers, the map() operation will take place only once.
- Subjects are considered as HOT Observables.
A HOT Observable, such as Subjects, emits items only once regardless of number of subscribers and its subscribers receive items only from the point of their subscription. Subjects convert cold observable into hot observable.
Example scenario: In the following example, we create a Subject which emits an integer from 1 to 4. We will add two Observers to observe the emission.
Output
Observer 1 onSubscribe
Observer 1 onNext: 1
Observer 1 onNext: 2
Observer 2 onSubscribe
Observer 1 onNext: 3
Observer 2 onNext: 3
Observer 1 onNext: 4
Observer 2 onNext: 4
You will notice from the above output that,
- Even though the Subject emits the integer value ‘0’, it is not printed. This is because there are no subscribers that are listening to the emission.
- Observer 2 only prints values ‘3’ and ‘4’. This is because the second Observer only subscribed to the Subject after it emitted values 0, 1 and 2.
Types of Subjects
PublishSubject
PublishSubject emits all the items at the point of subscription. This is the most basic form of Subject. We will use the sample example as above to illustrate this:
Output
Observer 1 onSubscribe
Observer 1 onNext: 1
Observer 1 onNext: 2
Observer 2 onSubscribe
Observer 1 onNext: 3
Observer 2 onNext: 3
Observer 1 onNext: 4
Observer 2 onNext: 4
BehaviorSubject
BehaviorSubject emits the most recent item at the time of their subscription and all items after that. We will use the sample example we used for PublishSubject.
Output
Observer 1 onSubscribe
Observer 1 onNext: 0
Observer 1 onNext: 1
Observer 1 onNext: 2
Observer 2 onSubscribe
Observer 2 onNext: 2
Observer 1 onNext: 3
Observer 2 onNext: 3
Observer 1 onNext: 4
Observer 2 onNext: 4
You will notice from the above output that BehaviorSubject prints the most recently emitted value before the subscription and all the values after the subscription.
Difference between PublishSubject and BehaviorSubject is that PublishSubject prints all values after subscription and BehaviorSubject prints the last emitted value before subscription and all the values after subscription.
ReplaySubject
ReplaySubject emits all the items of the Observable, regardless of when the subscriber subscribes. We will use the sample example we used for the previous two subjects.
Output
Observer 1 onSubscribe
Observer 1 onNext: 0
Observer 1 onNext: 1
Observer 1 onNext: 2
Observer 2 onSubscribe
Observer 2 onNext: 0
Observer 2 onNext: 1
Observer 2 onNext: 2
Observer 1 onNext: 3
Observer 2 onNext: 3
Observer 1 onNext: 4
Observer 2 onNext: 4
You will notice from the above output that all the items emitted by the subject are printed, regardless of when the subscription happened.
AsyncSubject
AsyncSubject emits only the last value of the Observable and this only happens after the Observable completes. Again, we will use the same example as above.
Output
Observer 1 onSubscribe
Observer 2 onSubscribe
Observer 1 onNext: 4
Observer 1 onComplete
Observer 2 onNext: 4
Observer 2 onComplete
You will notice that only after onComplete() is called, the last emitted value is printed by both Observers.
UnicastSubject
UnicastSubject allows only a single subscriber and it emits all the items regardless of the time of subscription. In the below example, we have an Observable that emits all integers from 1 to 5.
Output
onNext: 1
onNext: 2
onNext: 3
onNext: 4
onNext: 5
That’s it guys! This is part nine of the series on RxJava. I hope you enjoyed this article and found it useful, if so please hit the Clap button. Let me know your thoughts in the comments section.
Happy coding!