Migration to RxJava 2.x
Migration to RxJava 2.x
RxJava library has already become a standard in Android development. It gives engineers a way to think functionally and reactively. Recently RxJava 2.x was released. You can see the differences comparing to version 1.x here. It was also mentioned that further development of version 1.x will be stopped on the 31th of March 2018. Therefore, we have started slowly migrating to version RxJava 2.x.
We implement all new features using RxJava 2.x, and from time to time we do some refactoring in order to use the most recent version of it.
Here I would like to share some insights from our migration experience, some issues we found, and the way we solved them. This list might be helpful for you, if you decide to switch versions of RxJava.
We started using new types like Completable, Single, Maybe. They were in the experimental phase for a while, but in RxJava 2.x they were released as standard. So in which cases do we use them?
Completable is good when there is some task, which doesn’t return anything. Before we had to use
Observable<Void>, which submits
null value. Since in RxJava 2.x this is prohibited,
Completable type is a perfect data structure for that.
Single is basically used in all network interfaces defined for Retrofit. Because we know that the network call always returns one response, there’s no need to expect to receive more items from the stream.
Maybe can be used if you plan to return Optional value. The following type
Observable<Optional<Location>> can be replaced with
Maybe<Location>. In our case we had a situation when we needed to retrieve user location. But in some cases location is unavailable and
Maybe is ideal solution for such scenario.
Chain new types
Chaining operators is a nice way to keep your app functional. For
Single there is a method
toObservable(). The interesting part with
Completable is it also has
toObservable(). But after that Observable doesn’t submit any value and doesn’t complete since Completable doesn’t have any value and has already completed. However, there is a method
andThen() which accepts a source of the stream for continuation. Additionally there are the methods like
flatMapSingle(), which help to chain different types together.
RxJava Retrofit Adapter
If you use RxJava with Retrofit, you should use the appropriate adapter for Retrofit in this case. There are official adapters from Square for RxJava 1.x and for RxJava 2.x. It’s possible to have two of them at the same time - for version 1.x and 2.x.
Once your project uses both of the versions of RxJava, you arrive at a question: How can I switch or compound both versions at the same time? And there is an answer: There is a library RxJavaInterop. It helps a lot in converting types of different versions of RxJava. Now instead of global refactoring of the app, you can do it in small pieces applying the library. Check it out and you will see how useful it is.
Writing unit tests for classes and methods using RxJava also changed a bit. First, there are no
ImmediateScheduler anymore. Instead
Schedulers.trampoline() should be used.
Second, for each method returning RxJava stream type (
Completable etc.) there is a method
test(). It subscribes to the observable and returns
TestObserver on which you can do assertions. As mentioned, the type now is
TestObserver instead of
TestSubscriber. But, you can find
TestSubscriber as well. Well,
TestSubscriber is used now for
Default subscribe() method
Something interesting is also happening with subscribing to the stream. All the methods
subscribe() are returning now
Disposable type, except one. For
Observable it has the signature
void subscribe(Observer<? super T> observer). Pay attention next time if you want to pass a subscriber (observer) to
subscribe() method. In RxJava 1.x it was returning
Subscription. But in RxJava 2.x it’s void.
And the reason of that is:
Because Reactive-Streams base interface, org.reactivestreams.Publisher defines the subscribe() method as void, Flowable.subscribe(Subscriber) no longer returns any Subscription (or Disposable). The other base reactive types also follow this signature with their respective subscriber types.
The last point which I wanted to mention is the updated error handling method. It is very important. Our app started crashing in some cases when we started using RxJava 2.x. And the reason was that the stream already completed and the error occurred later. It can happen for different reasons. You can find good explanation of it in official manual in section Error Handling. Don’t ignore it and make sure all errors are handled properly.
In this article I wanted to share what we faced with migration to RxJava 2.x. Before migrating yourself, I would recommend that you to go through the list of changes in RxJava 2.x. It has enough information to alert you to any potential problems.