Matt’s Tidbits #72 — Migrating from RxJava 2 -> 3
Last week’s was a difficult post to write, which discussed issues of racism, bias, and privilege (and a new feature of Android Studio). 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:
- Convert all gradle imports from RxJava 2 to RxJava 3 (
implementation “io.reactivex.rxjava3:rxjava:3.0.4”
). - 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):
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 forObservable
has been removed — if you need to specify what happens on subscribe, use the.doOnSubscribe()
method. - The
startWith()
method forFlowable/Observable
has been split into multiple variants — eitherstartWithIterable()
,startWithItem()
, orstartWithArray()
. - The
flatMapSingle()
method forMaybe
has been replaced by a different function (originally calledflatMapSingleElement()
) — to achieve the previous behavior, now just call.toSingle()
. - The
Timed
class now throws a runtime Exception if you try to pass innull
for the initial value. - The
assertSubscribed()
,assertNotTerminated()
, and several otherTestSubscriber
methods have been removed, as they were determined to really only be useful internally to the RxJava library itself. - The
accept()
method for theConsumer
class now throws aThrowable
instead of anException
. - The
onErrorResumeNext()
method has been renamed toonErrorResumeWith()
. - The methods in the
Disposables
class have been merged into theDisposable
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:
- RxJavaInterop (converting from RxJava 1 <-> 2/3): https://github.com/akarnokd/RxJavaInterop
- 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.