Retrofit 2 — Cancel Requests

This is the second post taking a closer look at the new Retrofit 2 Call class. If you haven't read the first part, where we look on how to reuse and analyze the request using the Call class, check it out here.

In this blog post, we'll show you how to cancel requests and how to test if a request failed or was cancelled. Both can be very useful for app developers, who need to interact with APIs. If you're interested, keep reading!

Of course, we've a whole library of other Retrofit posts for you:

Retrofit Series Overview

  1. Introduction to Call Adapters (Coming soon)
  1. Callbacks (Coming soon)
  2. Annotations (Coming soon)
  3. Fluent Interface with Builders (Coming soon)

Cancel Requests

Let's use our example code from the how to download files with Retrofit blog post. But the exact request doesn't matter, since this is applicable to any Retrofit request. We've added a new activity, which creates a new request and executes it just like we usually do:

public class CallExampleActivity extends AppCompatActivity {

    public static final String TAG = "CallInstances";
    private Callback<ResponseBody> downloadCallback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_file_download);

        FileDownloadService downloadService = 
            ServiceGenerator.create(FileDownloadService.class);

        String fileUrl = "http://futurestud.io/test.mp4";
        Call<ResponseBody> call = 
            downloadService.downloadFileWithDynamicUrlSync(fileUrl);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                Log.d(TAG, "request success");
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.e(TAG, "request failed");
            }
        };);
    }

    // other methods
    // ...
}

Now let's assume the user clicked the "Abort" button or the app moved into a state where the request isn't necessary anymore: we need to cancel the request. In Retrofit 2, this can easily be done by using call.cancel();. This will either cancel the network request, if it's not already running, or not start the request at all. That's it! If we expand the relevant request code by a simple cancel action, it'd look like this:

String fileUrl = "http://futurestud.io/test.mp4";  
Call<ResponseBody> call =  
    downloadService.downloadFileWithDynamicUrlSync(fileUrl);
call.enqueue(new Callback<ResponseBody>() {  
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        Log.d(TAG, "request success");
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.e(TAG, "request failed");
    }
});
    }

// something happened, for example: user clicked cancel button
call.cancel();  
}

Check If Request Was Cancelled

If you cancel the request, Retrofit will classify this as a failed request and thus call the onFailure() callback in your request declaration. This callback is also used when there is no Internet connection or something went wrong on the network level. From the app perspective, these errors are quite a bit different. Thus, it's pretty helpful to know if a request was cancelled or if the device has no Internet connection.

Fortunately, the Call class offers a isCanceled() method to check whether the request was cancelled or not. With this little check you can distinguish various errors in your callback:

new Callback<ResponseBody>() {  
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                Log.d(TAG, "request success");
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                if (call.isCanceled()) {
                    Log.e(TAG, "request was cancelled");
                }
                else {
                    Log.e(TAG, "other larger issue, i.e. no network connection?");
                }

            }
        };

Summary

And that's it! Retrofit 2 makes it really easy to cancel requests and also check if a request was cancelled. It can be a very handy tool in your Retrofit toolset.

If you've any questions, let us know in the comments!

Explore the Library

Find interesting tutorials and solutions for your problems.

Miscellaneous