In case you haven’t heard: RxJava2 was released sometime back. RxJava 2 was a massive rewrite with breaking apis (but for good reasons). Most dependent libraries have upgraded by now though, so you’re safe to pull that migration trigger with your codebases.
Folks starting out directly with Rx2 might enjoy this guide but it’s the ones that started with Rx 1 that will probably appreciate it the most.
This is a continuation post in a 2 part series:
Let’s get started.
In this first part, I want to dive into making sense of the Rx2 changes from the point of view of an Rx1 user.
Why things changed with RxJava2
tl;dr- Reactive Streams spec
Reactive Streams is a standard for doing “reactive” programming and RxJava now implements the Reactive Streams specs with version 2.x. RxJava was sort of a trailblazer in reactive programming land but it wasn’t the only library around. There were others that also dealt with reactive paradigms. But with all the libraries adhering to the Reactive Streams spec now, interop between the libraries is a tad bit easier.
The spec per say is pretty straightforward with just 4 interfaces:
- Publisher (anything that publishes events, so
Observable
,Flowable
etc. - more on this later) - Subscriber (anything that listens to a Publisher)
- Subscription (
Publisher.subscribe(Subscriber) => Subscription
when you join a Publisher and a Subscriber, you are given a connection also called aSubscription
) - Processor (a Publisher + a Subscriber, sound familiar? yep
Subject
s for us RxJava 1 luddites)
If you’re slightly more curious about the design goals, I also suggest the following resources:
- What’s different in 2.0 wiki page - this is really the place I kept coming back to and referencing when I needed to understand the details
- Fragmented Ep #53 with JakeWharton (forgive the shameless promotion) - ultimate lazy person’s guide to understand why/what things changed with RxJava2, as explained by an actual demigod. This was the one that really made it first click for me.
- Thought process behind the 2.0 design for the truly loyal
- Ep 11 of The Context — by my friends Hannes and Artem :)
We should probably get one important change out of the way:
Dependency change
Search:
compile "io.reactivex:rxjava:${rxJavaVersion}"
compile "io.reactivex:rxandroid:${rxAndroidVersion}"
compile "com.jakewharton.rxbinding:rxbinding:${rxBindingsVersion}"
compile "com.squareup.retrofit2:adapter-rxjava:${retrofit2Version}"
Replace:
compile "io.reactivex.rxjava2:rxjava:${rxJavaVersion}"
compile "io.reactivex.rxjava2:rxandroid:${rxAndroidVersion}"
compile "com.jakewharton.rxbinding2:rxbinding:${rxBindingsVersion}"
compile "com.squareup.retrofit2:adapter-rxjava2:${retrofit2Version}"
A minor change in your gradle dependency pull (“2” suffix).
The actual classes though have been moved to a new package internally io.reactivex (vs rx). So you’ll have to change those import statements.
Also you “could” theoretically have both Rx1 and Rx2 running simultaneously but this is a bad idea because certain primary constructs like Observables have a very different notion of handling streams (backpressure). It can be a nightmare during that interim period where you have to remember the behavior differences. Also if you happen to use both Rx1 and Rx2 Observables you have to be careful about qualifying them explicitly with the right package name (rx.Observable
or io.reactivex.Observable
). This is very easy to mix up and get wrong.
Bite the bullet and migrate it all in one shot.
Another super important change:
Observable -> Flowable
Search : `import rx.Observable;`
Replace: `import io.reactivex.Flowable;`
- Flowable is the new Observable. Succinctly - it’s a backpressure-enabled base reactive class.
- You want to be using Flowable everywhere now, not Observable. Use this as your default.
- Observables are still available for use, but unless you really understand backpressure, you probably don’t want to be using them anymore.
Flowable = Observable + backpressure handling
Note on “Publisher"s:
Remember Publisher
? it’s basically the Reactive Streams interface for anything that produces events (Reread the Reactive Streams spec section above if this is not making sense).
Flowable
implements Publisher
. This is our new base default reactive class and implements the Reactive Streams spec 1 <-> 1. Think of of Flowable as primero uno “Publisher” (this is also partly the reason I recommend Flowable as the new default, in the previous section).
The other base reactive classes that are Publishers include Observable, Single, Completable and Maybe. But they don’t implement the Publisher
interface directly.
Why you ask?
Well the other base classes are now considered “Rx” specific constructs with specialized behavior pertaining to Rx. These are not necessarily notions you would find in the Reactive Streams specs.
We can look at the actual interface declarations and it’ll be clear.
Note on “Subscriber"s:
So if Publisher
is the Reactive Streams event producer, Subscriber
is the Reactive Streams event “listener” (it’s extremely helpful to keep these terms firmly grounded in our heads, hence the incessant repetition).
Looking at the actual interface code declaration should offer more clarity to the above two sections.
// Reactive Streams spec
// Flowable implements Publisher
interface Publisher<T> {
void subscribe(Subscriber<? super T> s);
}
As noted before, Publisher
and Subscriber
are part of the Reactive Streams spec. Flowable -which is now numero uno base reactive class of choice- implements Publisher
. All good so far.
But what about the other base reactive classes like Observable
and Single
that we’ve come to love and use?
On the publishing side, instead of implementing the standard Publisher
interface the other event producers implement a “similar” interface.
// RxJava specific constructs
// Observable implements "ObservableSource"
interface ObservableSource<T> {
void subscribe(Observer<? super T> observer);
// notice "Observer" here vs the standard "Subscriber"
}
// Single implements SingleSource
interface SingleSource<T> {
void subscribe(SingleObserver<? super T> observer);
}
interface CompletableSource {
void subscribe(CompletableObserver observer);
}
interface MaybeSource<T> {
void subscribe(MaybeObserver<? super T> observer);
}
Notice: instead of having the standard Subscriber
(Reactive Streams standard) the other base reactive classes (Observable
, Single
etc.) now have corresponding “special” Rx specific Subscriber
or event listeners called “Observer"s.
That’s it for Part 1. In the next part, we’ll look at disposing subscriptions.
My thanks to David Karnok & Donn Felker for reviewing this post.