Friday 4 August 2023

Retrofit 2 – Synchronous and Asynchronous Calls

 Learn to execute synchronous and asynchronous calls (i.e. blocking and non-blocking calls) in an android app using Retrofit2 and OkHttp library.

1. Call.execute() and Call.enqueue() Methods

In Retrofit 2, all requests are wrapped into a retrofit2.Call object. Each call yields its own HTTP request and response pair.

Call interface provides two methods for making the HTTP requests:

  • execute() – Synchronously send the request and return its response.
  • enqueue(retrofit2.Callback) – Asynchronously send the request and notify callback of its response or if an error occurred talking to the server, creating the request, or processing the response.

2. Retrofit Call Examples

2.1. Synchronous Call Example (Not recommended)

In synchronous calls, the request is sent using the execute() method and the request is blocked and the response is available immediately to the next statement.

In retrofit, synchronous methods are executed in the main thread. This means that the UI is blocked during the synchronous request execution and no user interaction is possible in this period.

Synchronous Request Example
UserService service = ServiceGenerator.createService(UserService.class); // 1. Calling '/api/users/2' - synchronously Call<UserApiResponse> callSync = service.getUser(2); try { Response<UserApiResponse> response = callSync.execute(); UserApiResponse apiResponse = response.body(); //API response System.out.println(apiResponse); } catch (Exception ex) { ex.printStackTrace(); }

In the above example, we have used the ServiceGenerator class. We have used ServiceGenerator class for having a centralized place to add/modify the authentication, logging and error handling logic.

ServiceGenerator.java
import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class ServiceGenerator { private static final String BASE_URL = "https://reqres.in/"; private static Retrofit.Builder builder = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()); private static Retrofit retrofit = builder.build(); private static HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor() .setLevel(HttpLoggingInterceptor.Level.BASIC); private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); public static <S> S createService(Class<S> serviceClass) { if (!httpClient.interceptors().contains(loggingInterceptor)) { httpClient.addInterceptor(loggingInterceptor); builder.client(httpClient.build()); } return retrofit.create(serviceClass); } }

2.2. Asynchronous Call Example (Recommended)

Asynchronous calls should be made for non-blocking UI. In this way, android executes the request in a separate thread and does not block the main thread.

It means the user can still interact with the app while waiting for the response.

Asynchronous request example
UserService service = ServiceGenerator.createService(UserService.class); // 2. Calling '/api/users/2' - asynchronously Call<UserApiResponse> callAsync = service.getUser(2); callAsync.enqueue(new Callback<UserApiResponse>() { @Override public void onResponse(Call<UserApiResponse> call, Response<UserApiResponse> response) { if (response.isSuccessful()) { UserApiResponse apiResponse = response.body(); //API response System.out.println(apiResponse); } else { System.out.println("Request Error :: " + response.errorBody()); } } @Override public void onFailure(Call<UserApiResponse> call, Throwable t) { System.out.println("Network Error :: " + t.getLocalizedMessage()); } });

Drop me your questions related to executing blocking and non-blocking calls in Retrofit 2.

No comments:

Post a Comment