Retrofit with RxJava
Let’s have a look at a theoretical introduction to Retrofit before we move on to coding.
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.