Matt's Tidbits #72 - Migrating from RxJava 2 -> 3
Tags: mattstidbits, android, rxjava, tidbittuesday
Published: 2020-06-16 13:58:36

[Last week's was a difficult post to write, which discussed issues of racism, bias, and privilege (and a new feature of Android Studio).](https://medium.com/@matthew.b.groves/matts-tidbits-71-trying-to-figure-out-what-to-say-cd7c14727e5f) This time, I want to share my story of migrating from RxJava 2 -> 3.

Staying current with the libraries you use in your app is essential to maintaining a secure, performant application. One such library is RxJava, which fairly aggressively releases new versions and deprecates old ones. RxJava 1 is now officially no longer supported, and even RxJava 2 will only continue to receive updates (critical security patches, etc.) until February of 2021. If you remember the RxJava 1 -> 2 migration, you may remember it was fairly painful - many things were renamed, and dropping support for `null` values in streams often required a lot of refactoring and cleanup to avoid runtime crashes.

The good news is, the RxJava 2 -> 3 migration is much more straightforward! The RxJava team has a very helpful article highlighting the differences: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-3.0

Here is the approach I took when migrating:
1. Convert all gradle imports from RxJava 2 to RxJava 3 (`implementation "io.reactivex.rxjava3:rxjava:3.0.4"`).

2. Do a find-and-replace to change code imports to the new packages (but don't "Optimize Imports" yet - I saved this for after my PR had been approved so it would make the review process easier):
![](https://cdn-images-1.medium.com/max/1600/1*MpD_fq2zc79AinQ1QhIxWQ.png)
<figcaption>I did the "Core" one last - it's a little tricky to find all of these, but when you try compiling your code, they will turn up - things like Flowable, Observable, Single, Maybe, Completable all fall into this package (along with their various Transformers).</figcaption>

3. Try to compile! You will likely see some errors. Then, start fixing them one-by-one. Here are some of the ones I ran into:

- The 4-argument `subscribe()` method for `Observable` has been removed - if you need to specify what happens on subscribe, use the `.doOnSubscribe()` method.
- The `startWith()` method for `Flowable/Observable` has been split into multiple variants - either `startWithIterable()`, `startWithItem()`, or `startWithArray()`.
- The `flatMapSingle()` method for `Maybe` has been replaced by a different function (originally called `flatMapSingleElement()`) - to achieve the previous behavior, now just call `.toSingle()`.
- The `Timed` class now throws a runtime Exception if you try to pass in `null` for the initial value.
- The `assertSubscribed()`, `assertNotTerminated()`, and several other `TestSubscriber` methods have been removed, as they were determined to really only be useful internally to the RxJava library itself.
- The `accept()` method for the `Consumer` class now throws a `Throwable` instead of an `Exception`.
- The `onErrorResumeNext()` method has been renamed to `onErrorResumeWith()`.
- The methods in the `Disposables` class have been merged into the `Disposable` interface.

As a result of this upgrade, some other related libraries also needed to be updated, including:
- RxLifecycle (to version 4+) (Gradle import + package rename to `com.trello.rxlifecycle4`)
- RxDogTag (to version 2+) (Gradle import + package rename to `rxdogtag2`)
- RxRelay (to version 3+) (Gradle import + package rename to `com.jakewharton.rxrelay3`)
- RxJavaInterop (to version 3+) (Gradle import + package rename to `hu.akarnokd.rxjava3.interop`)
- Retrofit (to version 2.9+) (Gradle import, package rename to `retrofit2.adapter.rxjava3`, and a new call adapter - `RxJava3CallAdapterFactory`)
- RxAndroid (to version 3+) (Gradle import + package rename to `io.reactivex.rxjava3.android`)

One last thing - if you find yourself needing to interface with older RxJava code (from other libraries - hopefully your app is consistent and uses the same version everywhere), there are two helper libraries you should know about:
1. RxJavaInterop (converting from RxJava 1 <-> 2/3): https://github.com/akarnokd/RxJavaInterop

2. RxJavaBridge (converting between RxJava 2 <-> 3): https://github.com/akarnokd/RxJavaBridge

I find it slightly irritating that these are separate libraries, but these are both VERY helpful if you want to keep your app on a single version of RxJava, as not all libraries have been updated to use RxJava3 yet - for instance, RxLifecycle, Retrofit, and RxRelay have all only been updated with RxJava 3 support in the last month.

So, if you have a little time on your hands, RxJava 3 now seems ready for primetime use! And thankfully, my own experience was that this conversion was fairly painless - the entire conversion was completed within 1 work day.

Please share your own experiences/tips for making the leap to RxJava 3, and let me know if you have any questions! And, please follow me on Medium if you're interested in being notified of future tidbits.

*This tidbit was discovered on June 10, 2020.*