Retrofit with RxJava

Let’s have a look at a theoretical introduction to Retrofit before we move on to coding.

For a more complete and in-depth explanation, check out our complete Retrofit course

Download the starter project here

Github repository

In this article we will not go into the details of RxJava itself or why you might want to use it. Personally I prefer to use coroutines, but if you are going to use RxJava firstly you need to know what RxJava is and how it works. If you do know that, you might find it easy to understand how you would use it in a project together with Retrofit.

The good news is Retrofit has complete support for RxJava so it’s quite easy to implement.

Libraries

The first thing we need to do in our code is make sure we have the required libraries for RxJava.

In the build.gradle app level file. In the dependencies you need the library references.

implementation “com.squareup.retrofit2:adapter-rxjava2:$retrofitVersion

implementation “io.reactivex.rxjava2:rxkotlin:2.4.0”

implementation “io.reactivex.rxjava2:rxandroid:2.1.1”

Make sure you sync the project so that gradle imports the libraries.

rxJava implementation

Once we have the libraries, we can go ahead and implement rxJava in code.

Let’s add a function in our ApiCall interface

@GET(“apiCall”)

fun callGetRx(): Single<ApiCallResponse>

The function will return a Single, which is an observable that only emits one value and then finishes.

In the ApiCallService class add a function to invoke the rxjava function we’ve just created.

private fun getApiRx() =

    Retrofit.Builder()

        .baseUrl(BASE_URL)

        .addConverterFactory(GsonConverterFactory.create())

        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

        .build()

        .create(ApiCall::class.java)

fun callRx() = getApiRx()

The RxJava2CallAdapterFactory takes the HTTP response that we get from the server and converts it to a Single observable.

Next, we need to update the MainViewModel to call the new RxJava function. Add a function to do that.

val compositeDisposable = CompositeDisposable()

fun fetchDataRx() {

    loading.value = true

    compositeDisposable.add(

        ApiCallService.callRx().callGetRx()

            .subscribeOn(Schedulers.io())

            .observeOn(AndroidSchedulers.mainThread())

            .subscribeWith(object : DisposableSingleObserver<ApiCallResponse>() {

                override fun onSuccess(response: ApiCallResponse) {

                    apiResponse.value = response.flatten()

                    error.value = null

                    loading.value = false

                }

                override fun onError(e: Throwable) {

                    onError(e.localizedMessage)

                }

            })

    )

}

override fun onCleared() {

    super.onCleared()

    job?.cancel()

    compositeDisposable.clear()

}

The compositeDisposable collects the references that are given by rxJava when we observe an object and when the ViewModel is destroyed, the references will be destroyed as well. That helps us sanitise the code so that we don’t have an memory leaks.

Since no network calls can be performed on the main thread of an Android application, rxJava will perform the operations on a background thread. That is what the subscribeOn call is for.

However, the response is received and processed on the main thread, which is achieved b the observeOn call.

The functionality for a success or a failure response is similar to the fetchData function.

Finally, we need to call this new function from the MainActivity. So we need to replace the existing call

//        viewModel.fetchData()

        viewModel.fetchDataRx()

Running the code will give us the same output as before. That of course makes sense since we are not changing the functionality itself, instead we are performing the same call in a different way.

For a more complete and in-depth explanation, check out our complete Retrofit course

Close Bitnami banner
Bitnami