Retrofit-Coroutine!!

KH Rafiqul Islam (Alik)
2 min readNov 26, 2019

--

Introduction

Retrofit 2.6.0 is now officially released in android. While it was already easy to use and fun, with new release it becomes for fun and shorter to write.

Suspend what you are doing, Retrofit becomes more fun and Retrofit has now coroutine support.

Before Retrofit 2.6.0

For better understanding, let's do some old code. I know you already know that but when I’m finished and migrating your code, you’ll notice how concise and simple is the new syntax.

Let’s do some old code.

@GET("profile")
fun callDriverProfile(@Header(Constant.TOKEN) token: String): Call<ProfileResponse>

in our repository class

fun callDriverProfile(token: String): Call<ProfileResponse> {
return apiService.callDriverProfile(token)
}

In our view model class, we’ll implement something like this. my way is not always right, you can have your own implementation, if my way works for you then I’m glad.

var mResponseModel: MutableLiveData<ProfileResponse>? = null
var mErrorModel
: MutableLiveData<String>? = null
var mLoading
: MutableLiveData<Boolean>? = MutableLiveData()

fun launchGetProfileInfo(token: String) {
viewModelScope.launch {
callGetProfileInfo(token)
}
}

suspend fun callGetProfileInfo(token: String) = withContext(Dispatchers.Default) {
mLoading
?.postValue(true)

mRepository.callDriverProfile(token).enqueue(object : Callback<ProfileResponse> {

override fun onFailure(call: Call<ProfileResponse>, t: Throwable) {
mLoading?.postValue(false)
val errorMessage = t.message
mErrorModel
?.postValue(errorMessage)
}

override fun onResponse(
call: Call<ProfileResponse>,
response: Response<ProfileResponse>
) {
if (response.isSuccessful) {
mResponseModel?.postValue(response.body())
mLoading?.postValue(false)
} else {
mLoading?.postValue(false)
val errorMessage = Utils.showErrorMessage(response)
mErrorModel?.postValue(errorMessage)
}
}
})
}

If you are not familiar with ViewModelScope, You can read my another article named Easy ViewModel and ViewModel Scope. Here are our normal code and anything you do you have to implement callbacks for thread switching. So lots of code.

On Retrofit 2.6.0

So now you can create suspend function in the new Retrofit update in your interface and directly return your response data.So now the method in interface looks something like this.

@POST("profile")
suspend fun callDriverProfile(@Header(Constant.TOKEN) token: String): ProfileResponse

At this point, the login in our repository class becomes more simple, something like this

suspend fun callDriverProfile(token: String) = apiService.callDriverProfile(token)

Activity is expecting LiveData to observe. LiveData’s building block already provides a Coroutine Scope were to call suspend functions like the one in our repository. So this becomes

val profileDataObserver = liveData (Dispatchers.IO){
val
profile = mRepository.callDriverProfile("header")
emit(profile)
}

The building block will automatically switch to the UI thread to update LiveData value when needed.

As we see migrating network code to coroutine and Retrofit 2.6.0 makes it cleaner and less boilerplate, especially with the callbacks.

But there is still some issue with this approach which they are going to be fixed soon with the new update. Retrofit 2.6.0 suspend function doesn’t support null response body yet :(

--

--