Humayun Tanwar
MindOrks
Published in
3 min readJul 17, 2019

--

Creating Custom Response Handler for Retrofit in Android

In this article we are going to discuss about the need to handle custom responses using retrofit2 in Android, and how to do it efficiently.

Sometimes when we are integrating web APIs into our Android Application, we come across systems which provide us with responses in their own custom object form. Where a variable such as “code” or “status” tells us about whether the response is accurate or not.
An example of this is as follow :

{
“code”: “0000”,
“message”: “Success”,
“Data”: “Hello World”
}
{
“code”: “1111”,
“message”: “Failed”,
“Data”: “Try again later”
}

As you can see the “code” variable tells us that the response is either success, or failure. Since we are receiving response the HTTP status code would be 200. which means we can’t use Interceptors to handle our response.

For this we will implement a custom Callback Class, which will handle our response codes and use this class in place of the default retrofit callback. This will allow us to only handle the success response separately and save us a’lot of time and the unnecessary overhead of handling the onFailure() method for every Request separately.

First of all we will create a data class which will map this response:

data class GeneralResponse(val code : String, 
val message : String,
val data : String)

now, we we will override the Callback class from the retrofit library and supply our data class to map the responses on, and override the onResponse() and onFailure() method.

lets also write our handling of on failure as it only needs to have one implementation in this class. Here I have simply logged whatever message we will receive as an exception, you can write any custom explanation.

open class RetrofitCallback() : Callback<GeneralResponse> {override fun onResponse(call: Call<GeneralResponse>, response: Response<GeneralResponse>) {}override fun onFailure(call: Call<GeneralResponse>, t: Throwable) {
if (t.message != null) {
Log.e(TAG, t.message)}
}
}

lets, move on to writing the implementation of onResponse() method where we will handle our custom responses and only leave the code “0000” response to be handled by the implementing Class.

override fun onResponse(call: Call<GeneralResponse>, response: Response<GeneralResponse>) {if (response.body() == null || response.code() == 404) {
//response is null
} else {
if (response.body()!!.code==”3333") {
//session timed out }
else if (response.body()!!.code==”1111") {
//failed }
}}
}

You can handle all the response codes here leaving out the code such as “0000” which will require different type of handling respective to the request call.

now, lets move on to the usage of this class and how we can use it in place of the Callback class. lets assume you have a API request that takes in some parameters and then use the en queue method to handle the response.

ApiUtils is class which creates a retrofit object which we will use to call our request named as ApiCall , which is a GET call and takes in two parameters named as params1 and params2.

ApiUtils.apiService.ApiCall(“params1”,”params2").
enqueue(
object : RetrofitCallback() {
override fun onResponse(call: Call<GeneralResponse>, response: Response<GeneralResponse>) {
super.onResponse(call, response)
when (response.body()!!.code) {
“0000” ->
Log(“Sucess”, “post success to API. “)
}
}
}

as you can see this can be very advantageous to us, as we don’t need to handle the onFailure() and repeated responses again and again , but only need to handle the success response code for our API request.

now what if you want to show some sort of progress dialog on every request call, we can simply add “context” as a parameter to the object of our custom class and use it to show the progress dialog. lets make some changes to our class constructor implementation. create a method to hide the progress dialog as well, and we can use this method in both of onResponse() and onFailure() method.

open class RetrofitCallback(private val mContext: Context) : Callback<GeneralResponse> {
private lateinit var progressDialog: Dialog
init {
//make sure to initilize your progress dialog
progressDialog = Util.getProgressDialog(mContext)
progressDialog.show()
}
private fun hideProgress() {
progressDialog.dismiss()
}

Now lets combine all things together and make it work.

--

--