Retrofit — Synchronous and Asynchronous Requests

Retrofit — Synchronous and Asynchronous Requests

Within the previously published tutorials, we walked you through the setup of Retrofit. This tutorial shows you how to perform the actual requests in either a synchronous or a asynchronous way.


Retrofit Series Overview

  1. Getting Started and Creating an Android Client
  2. Retrofit 2 — Basics of API Description
  3. Retrofit 2 — Creating a Sustainable Android Client
  4. Synchronous and Asynchronous Requests
  5. Send Objects in Request Body
  6. Add Custom Request Header
  7. Retrofit 2 — Manage Request Headers in OkHttp Interceptor
  8. Retrofit 2 — Dynamic Request Headers with @HeaderMap
  9. Multiple Query Parameters of Same Name
  10. Optional Query Parameters
  11. Using the Log Level to Debug Requests
  12. Retrofit 2 — Log Requests and Responses
  13. Retrofit 2 — Enable Logging for Development Builds Only
  14. How to Upload Files to Server
  15. Retrofit 2 — How to Upload Files to Server
  16. Retrofit 2 — How to Upload Multiple Files to Server
  17. Retrofit 2 — Passing Multiple Parts Along a File with @PartMap
  18. Basic Authentication on Android
  19. Token Authentication on Android
  20. OAuth on Android
  21. Retrofit 2 — Hawk Authentication on Android
  22. How to Refresh an Access Token
  23. Retrofit 2 — Upgrade Guide from 1.9
  24. Retrofit 2 — Simple Error Handling
  25. How to use OkHttp 3 with Retrofit 1
  26. Send Data Form-Urlencoded
  27. Send Data Form-Urlencoded Using FieldMap
  28. Retrofit 2 — How to Add Query Parameters to Every Request
  29. Retrofit 2 — Add Multiple Query Parameter With QueryMap
  30. Retrofit 2 — How to Use Dynamic Urls for Requests
  31. Retrofit 2 — URL Handling, Resolution and Parsing
  32. Retrofit 2 — Constant, Default and Logic Values for POST and PUT Requests
  33. Retrofit 2 — How to Download Files from Server
  34. Retrofit 2 — Cancel Requests
  35. Retrofit 2 — Reuse and Analyze Requests
  36. Retrofit 2 — How to Change API Base Url at Runtime
  37. Optional Path Parameters
  38. Retrofit 2 — How to Send Plain Text Request Body
  39. Retrofit 2 — Pagination Using Query Parameter
  40. Retrofit 2 — Pagination Using Link Header and Dynamic Urls (Like GitHub)
  41. Retrofit 2 — Pagination Using Range Header Fields (Like Heroku)
  42. How to Integrate XML Converter
  43. Define a Custom Response Converter
  44. Retrofit 2 — Introduction to (Multiple) Converters
  45. Retrofit 2 — Adding & Customizing the Gson Converter
  46. Retrofit 2 — Implementing Custom Converters
  47. Retrofit 2 — Basics of Mocking Server Responses
  48. Retrofit 2 — Customizing Network Behavior of Mocked Server Responses (soon)
  49. Java Basics for Retrofit — Callbacks (soon)
  50. Java Basics for Retrofit — Annotations (soon)
  51. Java Basics for Retrofit — Fluent Interface with Builders (soon)

TL;DR
Retrofit supports synchronous and asynchronous request execution. Users define the concrete execution by setting a return type (synchronous) or not (asynchronous) to service methods.

Synchronous Requests

Synchronous requests with Retrofit 1.9 are declared by defining a return type. The example below expects a list of tasks as the response when executing the method getTasks.

Retrofit 2

public interface TaskService {  
    @GET("/tasks")
    Call<List<Task>> getTasks();
}

Retrofit 1.9

public interface TaskService {  
    @GET("/tasks")
    List<Task> getTasks();
}

Within Retrofit 2, every request is wrapped into a Call object. The actual synchronous or asynchronous request is executed differently using the desired method on a later created call object. However, the interface definition for synchronous and asynchronous requests are the same within Retrofit 2.

Synchronous methods are executed on the main thread. That means the UI blocks during request execution and no interaction is possible for this period.

Synchronous methods provide the ability to use the return value directly, because the operation blocks everything else during your network request.

For non-blocking UI, you have to handle the request execution in a separated thread by yourself. That means, you can still interact with the app itself while waiting for the response.

Get Results from Synchronous Requests

Let’s move to the point where we execute the actual request. This behavior changed from Retrofit v1 to v2. The following code snippets illustrate the synchronous request execution with Retrofit and assume that you’re familiar with the ServiceGenerator class introduced in the tutorial on how to create a sustainable Android client.

Retrofit 2

TaskService taskService = ServiceGenerator.createService(TaskService.class);  
Call<List<Task>> call = taskService.getTasks();  
List<Task>> tasks = call.execute().body();  

Retrofit 1.9

TaskService taskService = ServiceGenerator.createService(TaskService.class);  
List<Task> tasks = taskService.getTasks();  

Using the .execute() method on a call object will perform the synchronous request in Retrofit 2. The deserialized response body is available via the .body() method on the response object.

Asynchronous Requests

Additionally to synchronous calls, Retrofit supports asynchronous requests out of the box. Asynchronous requests in Retrofit 1.9 don’t have a return type. Instead, the defined method requires a typed callback as last method parameter.

Retrofit 2

public interface TaskService {  
    @GET("/tasks")
    Call<List<Task>> getTasks();
}

Retrofit 1.9

public interface TaskService {  
    @GET("/tasks")
    void getTasks(Callback<List<Task>> cb);
}

Retrofit performs and handles the method execution in a separated thread. The Callback class is generic and maps your defined return type. Our example returns a list of tasks and the Callback does the mapping internally.

As already mentioned above: the interface definition in Retrofit 2 is the same for synchronous and asynchronous requests. The desired return type is encapsulated into a Call object and the actual request execution defines its type (synchronous/asynchronous).

Get Results from Asynchronous Requests

Using asynchronous requests forces you to implement a Callback with its two callback methods: success and failure. When calling the asynchronous getTasks() method from a service class, you have to implement a new Callback and define what should be done once the request finishes. The following code snippet illustrates an exemplary implementation.

Retrofit 2

TaskService taskService = ServiceGenerator.createService(TaskService.class);  
Call<List<Task>> call = taskService.getTasks();  
call.enqueue(new Callback<List<Task>>() {  
    @Override
    public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {
        if (response.isSuccessful()) {
            // tasks available
        } else {
            // error response, no access to resource?
        }
    }

    @Override
    public void onFailure(Call<List<Task>> call, Throwable t) {
        // something went completely south (like no internet connection)
        Log.d("Error", t.getMessage());
    }
}

Retrofit 1.9

TaskService taskService = ServiceGenerator.createService(TaskService.class);  
taskService.getTasks(new Callback<List<Task>>() {  
    @Override
    public void success(List<Task> tasks, Response response) {
        // here you do stuff with returned tasks
    }

    @Override
    public void failure(RetrofitError error) {
        // you should handle errors, too
    }
});

Get Raw HTTP Response

In case you need the raw HTTP response object, just define it as the method’s return type. The Response class applies to both methods like any other class.

Retrofit 2

The way you can receive the raw response body in Retrofit 2 has change to v1 the same way you define the request type (sync/async). Namely, you don’t need to define the Response class as the return type, but you can grab it within the onResponse() callback method. Let’s look at the following code snippet to illustrate how you can get the raw response:

call.enqueue(new Callback<List<Task>>() {  
    @Override
    public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {
        // get raw response
        Response raw = response.raw();
    }

    @Override
    public void onFailure(Call<List<Task>> call, Throwable t) {}
}

Retrofit 1.9

// synchronous
@GET("/tasks")
Response getTasks();

// asynchronous
@GET("/tasks")
void getTasks(Callback<Response> cb);  

Happy coding! If you run into problems or need help, please find us on Twitter @futurestud_io.


Additional Resources


Explore the Library

Find interesting tutorials and solutions for your problems.

Miscellaneous