Eliminate nullability with RxJava
Hello everyone and welcome to my FIRST POST! I will share short story of mine that will show what the problem is, how I solved it with RxJava, and why I used RxJava even tho I haven’t used it since Kotlin Coroutines appeared.
Before I begin I will say that if you are new to async (RxJava/Coroutines) thing and you are asking yourself should you go with RxJava or Kotlin Coroutines go with Kotlin Coroutines. RxJava has it’s good sides but it’s built for Java and not for Kotlin. Kotlin Coroutines allow you to write idiomatic Kotlin code. This article assumes familiarity with RxJava.
Story time! Recently I’ve joined one Android project. Project was built by some guys in a record time (you know that’s not good, right?) and as you would suspect code is a TOTAL MESS. App is written in Kotlin but that Kotlin code is written as you would write Java code. Code is really bad and EVERYTHING is done on MainThread. Realm is used as a database together with some outdated library that makes it Kotlin friendly. And (that’s why we are here) app relies heavily on null values and null checks. App has been given to one other developer to continue adding features and maintain it. He saw problem with performance and started to move database reads/writes of the MainThread. For that he used RxJava. That answers question “Why I used RxJava?” :D. Caviat, he is new to RxJava. He wrapped everything in Single.fromCallable {} and that’s it. Nulls are still present.
With mine 2 years of experience with RxJava I can add some value to the project.
With Single<T> we just get offloading work to background thread but bad code with null checks stays.
Solution. From RxJava kit, what can help us avoid null values? It’s Maybe!
Above snippet is copied from http://reactivex.io/RxJava/javadoc/io/reactivex/Maybe.html.
As we can see Maybe<T> can emit value, emit error or simply complete with no value if there are no values to emit. How we can use it? If value we need is not null we emit it (onSuccess()), if there was problem getting the value error is emitted (onError()) and finally if value is null we simply complete (onComplete()). As name says maybe value is there, maybe it’s not.
But how to implement it? I’ve got you covered.
We have eliminitted null and replaced it with Maybe. This Maybe will only emit if value we need is not null.
This is how it looks like when we subscribe to it in order to get value:
If you want this to be asynchronous you need to wrap it in Maybe.defer{}. Like this, for example:
You also have Maybe.fromCallable {} that will emit any non null value. You choose what suits you best.
I will not cover disposing and managing subscriptions in this post. Write in the comments if you are interested in that.
That’s it! Simple, right? I hope this post was helpful. Take care everyone!