Skip to content

What it is

Retrofit is a type-safe HTTP client for Java and Android, developed by Square. It allows you to define REST API endpoints as Java interfaces and automatically converts HTTP responses into Java objects using converters like Gson or Jackson.

Retrofit allows developers to define API endpoints in Java interfaces, handle requests and responses easily, and integrate with JSON converters. It supports query parameters, path variables, headers, and multipart requests.

Installation

Add com.squareup.retrofit2:retrofit dependency in pom.xml

Getting started

The smallest useful thing you can do with it, and what each part means.

Defining a simple API interface
import retrofit2.Call;
import retrofit2.http.GET;

public interface ApiService {
    @GET("users")
    Call<List<User>> getUsers();
}
Defines a GET request to fetch a list of users from the `/users` endpoint.
Creating Retrofit instance
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.example.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

ApiService service = retrofit.create(ApiService.class);
Creates a Retrofit instance with a base URL and a Gson converter for JSON parsing.

Advanced usage

Where the library earns its place over a simpler alternative.

Making synchronous requests
Call<List<User>> call = service.getUsers();
try {
    List<User> users = call.execute().body();
    System.out.println(users);
} catch (IOException e) {
    e.printStackTrace();
}
Executes a request synchronously and retrieves the response body.
Making asynchronous requests
call.enqueue(new retrofit2.Callback<List<User>>() {
    @Override
    public void onResponse(Call<List<User>> call, retrofit2.Response<List<User>> response) {
        System.out.println(response.body());
    }
    @Override
    public void onFailure(Call<List<User>> call, Throwable t) {
        t.printStackTrace();
    }
});
Executes a request asynchronously using a callback.
Using path and query parameters
import retrofit2.http.Path;
import retrofit2.http.Query;

@GET("users/{id}")
Call<User> getUser(@Path("id") int id, @Query("expand") boolean expandDetails);
Shows how to pass dynamic path variables and query parameters in API calls.
Adding headers
@GET("users")
@Headers({"Authorization: Bearer TOKEN"})
Call<List<User>> getUsersWithAuth();
Demonstrates setting static headers for a specific API request.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

IOException
Occurs when a network request fails. Check connectivity and URL.
HttpException
Thrown when the HTTP response is not successful (non-2xx). Check status code and response body.
JsonSyntaxException
Occurs when JSON response cannot be parsed into the specified Java object. Ensure matching fields and types.

Best practices

  • Reuse Retrofit instances to leverage connection pooling.
  • Use converters like Gson, Jackson, or Moshi for serialization/deserialization.
  • Handle errors and HTTP status codes in the callback.
  • Prefer asynchronous requests for network operations to avoid blocking threads.
  • Leverage OkHttp interceptors for logging, authentication, and retries.

Background

Why it exists, and what it was reacting to.

Retrofit was created by Square to simplify the process of consuming REST APIs in Java applications. By leveraging annotations, it abstracts network calls, handles serialization/deserialization, and supports synchronous and asynchronous requests.