Retrofit canceling requests

How to cancel requests that are no longer necessary in Retrofit

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

Download the starter project here

Github repository

There are a few different reasons why you might want to cancel a request. It may be taking too long and you have a system in place that says if it takes longer than 3 seconds then you want to cancel that request. Or the user simply navigates away from that screen and you don’t need that request anymore. Whatever the reason may be there is of course a way to cancel a request in Retrofit.

And that is actually quite simple, we have a function in the call object to do that

call.cancel()

To show you how it works, we’re going to put it in place in our code.

In the MainViewModel class, update the fetchData function by adding the cancellation at the end.

fun fetchData() {

    loading.value = true

    val call = ApiCallService.call()

    call.enqueue(object: Callback<ApiCallResponse> {

        override fun onResponse(call: Call<ApiCallResponse>, response: Response<ApiCallResponse>) {

            val body = response.body()

            apiResponse.value = body?.flatten()

            error.value = null

            loading.value = false

        }

        override fun onFailure(call: Call<ApiCallResponse>, t: Throwable) {

            onError(t.localizedMessage)

        }

    })

    call.cancel()

}

canceled

Running the app will give us a cancelled message that is displayed as an error.

So why is that? What happens is when we cancel a request, the system interprets that as an onFailure call. So we get an error response.

In some situations that might not be ideal. You might want to personalise your error message or your output to the user depending on whether the request was cancelled or it actually failed.

In order to do that we have a simple flag

call.isCanceled

So that will give us a true or false if the request was canceled or not.

We can use that in our code as well. Update the fetchData() method in the MainViewModel class.

fun fetchData() {

    loading.value = true

    val call = ApiCallService.call()

    call.enqueue(object: Callback<ApiCallResponse> {

        override fun onResponse(call: Call<ApiCallResponse>, response: Response<ApiCallResponse>) {

            val body = response.body()

            apiResponse.value = body?.flatten()

            error.value = null

            loading.value = false

        }

        override fun onFailure(call: Call<ApiCallResponse>, t: Throwable) {

            if (call.isCanceled) {

                onError(“The call was canceled”)

            } else {

                onError(t.localizedMessage)

            }

        }

    })

    call.cancel()

}

canceled personalized

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

Close Bitnami banner
Bitnami