Back in the good ol’ days of MVP, the combination of RxJava and Retrofit was almost an absolute. It only made perfect sense to return API calls as Observables that can be easily mapped and manipulated in ways limited only by imagination.

While MVVM can still just as easily make use of RxJava, there are reasons why you wouldn’t want to (that we won’t get into here) and instead, choose the wonderful world of LiveData.

Why doesn’t LiveData work so well with API calls, you may ask? We could potentially create an adapter that maps the Retrofit Call to the LiveData, but the underlying problem here is the lack of the ability to return an error value. There is a workaround to this which we have as one of our 3 solutions, but we’ll get to that later.

For this tutorial, I’ll be using the JSONPlaceholder API. Particularly, this one:

This tutorial does of course, require you to know about MVVM, LiveData, and Retrofit. We’ll also be going through as if we already have Retrofit set up in our app.

Method 1: Using Standard Calls

We’ll start off, firstly with the normal way to do it. Use your repository to enqueue a call and update your LiveData in its callbacks.

While easily quite stable and easy to use, piling callbacks like this can get messy very quickly… and that’s pretty much the main disadvantage of this method.

Method 2: Using Coroutines

As of Retrofit 2.6.0, we now have official support for coroutines.

We’ll need to add a few extra dependencies

Also, make sure your Kotlin is up to date with the latest version to ensure coroutines are working.

With that, we simply change our API call from this

To this

Then in our repository, we change our getPosts() function to this sexy one-liner

Then our ViewModel function changes to this

No change is required in our Activity, as it should be.

While easily the most concise solution here, it’s not without its problems. Firstly, since we are making use of dependencies that are still in their alpha builds, we can’t guarantee stability. Suspend functions also don’t yet support null API response bodies, but that’s an issue in the works.

Method 3: Creating our own Adapter

This solution was created by pavincii, I suggest you go check him out.

This method takes advantage of the fact we can set our own Call Adapters to our Retrofit instance. Here’s the adapter panincii made

We’ll also need to define the class ApiResponse

The reason for this is that LiveData doesn’t provide any error callbacks so we need to have a way to handle them.

Then we need to create a factory for this adapter

We then update our Retrofit Builder to include this Call Adapter

Then finally, we make our Api call return a LiveData

It does have a few inherent problems like how are we going to refresh data? This feels more like a use-case for the equivalent of RxJava’s Single, rather than an Observable.