Cleaner Code With RxJava, Coroutines Kotlin Extensions, and Helper Functions

Kotlinizing RxJava and Coroutines for Android development

JankiKhan
Better Programming

--

Two leaves in a vase of water
Photo by Sarah Dorweiler on Unsplash

In this article, I will be explaining some of the Kotlin extensions and helper functions that I wrote for RxJava and Coroutines while introducing reactive patterns to my Android applications. I will be assuming that you have some familiarity with those libraries.

For each extension, I will describe the use case, how it can be implemented without an extension, how I’d prefer it to be used, and the extension that will implement that preferred way of using it. So without further ado, let us begin.

Scenario 1. Room With RxJava

Let’s say you have a Room query that returns a Flowable; this is a typical use case that enables us to observe the database and act accordingly whenever an update occurs. What happens when we want to invoke that Room query only once without observing it? We can of course always create another query with a different return type, and that’s definitely the way to go in some cases, but if we still want to take advantage of RxJava in that case, we can write a simple extension for that.

The extension ideally would return a single invocation result on success and would allow for failure handling. The signature of that extension would look like this:

Database Single Invocation Signature

If we take a look at the Flowable class, you’ll notice there is a function called blockingFirst() which returns the first item emitted. It will throw a NoSuchElementException if it emits no items and will throw a RuntimeException if the source signals an error.

We can utilize this information to write the following extension function:

Database Single Invocation Extension Function

I separated both types of exceptions just to highlight the fact that you can catch the NoSuchElementException specifically. To use that extension let’s assume you have a database query that looks like this:

Get All Tasks from Room Database Query

To invoke this query once without having to observe it, you can use the extension function like this:

Get All Tasks from Room Database Query Usage

It’s worth mentioning that RxJava in general has an inherent ugliness in its nested nature; as you can imagine, with more complex logic the nesting might get out of hand. This issue can be solved with Coroutines; but for now, this extension will make it much cleaner than its straightforward implementation equivalent.

Scenario 2. Retrofit With RxJava

If you ever used RxJava for Retrofit network calls, then you’d know that RxJava handles HTTP errors (such as a 404) differently from other network errors (such as no internet connection), and that adds a lot of boilerplate code to every network call you make.

Ideally we’d be able to have an extension that accepts a success handler, a failure handler, and a completion handler, and that’s all we’d care about. The extension’s signature would look like this:

RxJava Retrofit Extension Signature

Notice that the Observable holds a Retrofit Response object, which would be what we wrap our network response objects with; this way we can identify HTTP errors. We’d like the onFailure to be called when any failure happens (HTTP or network), the onComplete to be called after the network call, whether it succeeds or not, and the onSuccess to be called if the network call is successful.

With that information in hand, here’s what the extension would look like:

RxJava Retrofit Extension Implementation

Notice that we have to invoke onComplete in two places; that’s because doOnComplete will not be called if a network error occurs. If we get an HTTP error, then we can wrap the response inside an HttpException and use that in the onFailure handler.

On top of the onFailure handler that we’re passing as a parameter, we can also have a universal error handler, and it would look something like this:

RxJava Retrofit Extension Implementation with Universal Error Handler

To use this extension, let’s assume you have a getTasks GET request such as this one:

Retrofit GET Request with RxJava

Now all you have to do to invoke this GET request is to write this code:

RxJava Retrofit Extension Usage

Note that you can choose not to pass an onFailure and an onComplete if you choose not to care about those for a specific use case.

Scenario 3. Retrofit With Coroutines

If you want to do the same thing that we did in Scenario 2 but with Coroutines, we can write a quick helper function instead of an extension. The function’s signature can look like this:

Coroutines Retrofit Helper Function Signature

With the use of suspend functions, using Coroutines will be much cleaner. As you can see, we don’t need to pass an onSuccess handler because we can identify a success by returning a value; otherwise we can return null. We also don’t need an onComplete handler because anything we do after the call will be after completion.

The implementation of this helper function can look like this:

Coroutines Retrofit Helper Function Implementation

With this type of implementation you can easily add a universal error handler on top of the optional error handler you pass in this method; maybe you’d want to add some universal analytics or maybe you want to show a Snackbar for all network errors across the entire application. With that addition, it’ll look more like this:

Coroutines Retrofit Helper Function Implementation with a Universal Error Handler

To use this helper function, let’s assume you have a getTasks Retrofit function that looks like this:

Retrofit GET Request with Coroutines

Then you can use it inside a CoroutineScope, let’s say in the ViewModel, like this:

Retrofit GET Request with Coroutines Usage in a ViewModel

As a final thought, I do realize that RxJava can still be useful, but I find that using Coroutines is much cleaner here and also doesn’t suffer from the nesting effect that RxJava has.

That’s it for this article. I hope you got some use out of it and that it helped you write cleaner code. Until next time, Dev Bites signing out!

--

--

Dev Bites is all about programming, currently launching in written form, and soon to be on YouTube and Podcast forms! Stay tuned!