Retrofit для Java: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Retrofit для Java: Type-safe HTTP клиент для Android и Java

1. Что это и зачем нужна

Retrofit — это мощная и элегантная библиотека для Java (и Android), которая превращает HTTP API в Java-интерфейс. Вместо того чтобы вручную писать шаблонный код для создания HTTP-запросов, обработки ответов и парсинга JSON, Retrofit делает всю эту работу за вас. Она автоматически сериализует ваши Java-объекты в JSON (или другой формат) для отправки на сервер и десериализует ответы сервера обратно в Java-объекты. Это делает код чистым, читаемым и легко поддерживаемым.

Зачем она нужна? Представьте, что вам нужно написать приложение, которое общается с REST API (например, GitHub API, OpenWeatherMap или вашим собственным сервером). Без Retrofit вам пришлось бы использовать низкоуровневые классы вроде HttpURLConnection или HttpClient, вручную формировать URL, устанавливать заголовки, обрабатывать коды ошибок и парсить JSON. Это не только утомительно, но и чревато ошибками. Retrofit решает эти проблемы, предоставляя декларативный способ описания API. Вы просто создаете интерфейс с методами, аннотируете их (например, @GET, @POST), и Retrofit сам генерирует реализацию этого интерфейса.

Retrofit — это стандарт де-факто для работы с HTTP в мире Android и Java. Он тесно интегрируется с OkHttp (для эффективной работы с сетью) и Gson/Moshi (для сериализации JSON). Библиотека поддерживает синхронные и асинхронные запросы, загрузку файлов, аутентификацию, кэширование и множество других возможностей. Благодаря своей простоте и гибкости, Retrofit используется в тысячах приложений и сервисов по всему миру.

2. Установка

Retrofit распространяется через Maven Central. Для его использования в вашем проекте на Java (например, с Maven или Gradle) добавьте соответствующие зависимости. Обратите внимание, что вам также понадобится конвертер для сериализации (чаще всего Gson или Moshi) и сам OkHttp (который Retrofit использует под капотом).

Maven (pom.xml)

<!-- Retrofit -->
<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>retrofit</artifactId>
    <version>2.9.0</version>
</dependency>

<!-- Конвертер Gson (для JSON) -->
<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>converter-gson</artifactId>
    <version>2.9.0</version>
</dependency>

<!-- OkHttp (обычно подтягивается автоматически, но можно явно указать версию) -->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.12.0</version>
</dependency>

Gradle (build.gradle)

dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
}

Важно: Версии могут устаревать. Всегда проверяйте актуальные версии на официальном сайте или в репозитории Maven Central. Если вы используете другой конвертер (например, Moshi или Jackson), замените converter-gson на соответствующий артефакт (converter-moshi, converter-jackson).

3. Быстрый старт — минимальный рабочий пример

Давайте напишем простой пример, который получает список пользователей с сервера JSONPlaceholder (тестовый REST API).

Шаг 1: Создайте модель данных (POJO)

// User.java
public class User {
    private int id;
    private String name;
    private String username;
    private String email;

    // Геттеры (обязательны для Gson)
    public int getId() { return id; }
    public String getName() { return name; }
    public String getUsername() { return username; }
    public String getEmail() { return email; }
}

Шаг 2: Создайте интерфейс API

// ApiService.java
import retrofit2.Call;
import retrofit2.http.GET;
import java.util.List;

public interface ApiService {
    @GET("users")
    Call<List<User>> getUsers();
}

Шаг 3: Создайте экземпляр Retrofit и выполните запрос

// Main.java
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class Main {
    public static void main(String[] args) {
        // 1. Создаем Retrofit-билдер
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://jsonplaceholder.typicode.com/") // Базовый URL
                .addConverterFactory(GsonConverterFactory.create()) // Конвертер JSON
                .build();

        // 2. Создаем реализацию интерфейса
        ApiService service = retrofit.create(ApiService.class);

        // 3. Создаем "Call" объект
        Call<List<User>> call = service.getUsers();

        // 4. Выполняем запрос асинхронно
        call.enqueue(new Callback<List<User>>() {
            @Override
            public void onResponse(Call<List<User>> call, Response<List<User>> response) {
                if (response.isSuccessful()) {
                    List<User> users = response.body();
                    for (User user : users) {
                        System.out.println(user.getName() + " (" + user.getEmail() + ")");
                    }
                } else {
                    System.out.println("Ошибка: " + response.code());
                }
            }

            @Override
            public void onFailure(Call<List<User>> call, Throwable t) {
                System.err.println("Ошибка сети: " + t.getMessage());
            }
        });

        // Ждем завершения асинхронного запроса (для демонстрации)
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Этот код выведет в консоль имена и email первых 10 пользователей с тестового сервера.

4. Основные методы/функции/классы

Рассмотрим ключевые компоненты Retrofit, которые вы будете использовать постоянно.

4.1. Retrofit.Builder

Сигнатура: public static class Builder

Что делает: Это строитель (Builder pattern) для создания экземпляра Retrofit. Позволяет настроить базовый URL, конвертеры, HTTP-клиент (OkHttp), пул соединений и другие параметры.

Пример:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.example.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .client(new OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .build())
    .build();

4.2. Retrofit.create()

Сигнатура: public <T> T create(final Class<T> service)

Что делает: Создает реализацию вашего API-интерфейса. Возвращает прокси-объект, который перехватывает вызовы методов и преобразует их в HTTP-запросы.

Пример:

ApiService service = retrofit.create(ApiService.class);

4.3. @GET, @POST, @PUT, @DELETE, @PATCH

Сигнатура: @GET("relative/path"), @POST("relative/path") и т.д.

Что делает: Аннотации, которые указывают HTTP-метод и относительный путь запроса. Путь может содержать динамические сегменты (см. @Path).

Пример:

public interface ApiService {
    @GET("users/{id}")
    Call<User> getUser(@Path("id") int userId);

    @POST("users")
    Call<User> createUser(@Body User user);

    @DELETE("users/{id}")
    Call<Void> deleteUser(@Path("id") int userId);
}

4.4. @Path

Сигнатура: @Path("name") Type parameter

Что делает: Заменяет динамический сегмент в URL-пути на значение параметра метода. Имя в аннотации должно совпадать с именем в фигурных скобках в @GET или другом методе.

Пример:

@GET("users/{id}/posts")
Call<List<Post>> getUserPosts(@Path("id") int userId);

4.5. @Query и @QueryMap

Сигнатура: @Query("key") Type value, @QueryMap Map<String, String> options

Что делает: Добавляет параметры запроса (query parameters) к URL. @Query для одного параметра, @QueryMap для динамического набора параметров.

Пример:

@GET("users")
Call<List<User>> getUsers(@Query("page") int page, @Query("limit") int limit);

@GET("search")
Call<List<Result>> search(@QueryMap Map<String, String> filters);

4.6. @Body

Сигнатура: @Body Object body

Что делает: Аннотирует параметр метода, который будет сериализован в тело запроса (обычно в JSON или XML). Используется с @POST, @PUT, @PATCH.

Пример:

@POST("users")
Call<User> createUser(@Body User newUser);
@Header и @Headers

Сигнатура: @Header("Authorization") String token, @Headers({"Cache-Control: max-age=640000", "User-Agent: My-App"})

Что делает: Позволяет добавлять HTTP-заголовки к запросу. @Header используется для динамических заголовков (значение передается как параметр), @Headers — для статических.

Пример:

@GET("user/profile")
Call<Profile> getProfile(@Header("Authorization") String authToken);

@Headers("Content-Type: application/json")
@POST("data")
Call<ResponseBody> postData(@Body RequestData data);

4.8. Call<T>

Сигнатура: public interface Call<T> extends Cloneable

Что делает: Представляет собой один HTTP-запрос, который может быть выполнен. Содержит методы execute() (синхронный) и enqueue(Callback) (асинхронный). Также можно отменить запрос через cancel().

Пример:

// Синхронный вызов (блокирует поток)
Response<User> response = call.execute();
User user = response.body();

// Асинхронный вызов
call.enqueue(new Callback<User>() {
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        // Обработка успешного ответа
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {
        // Обработка ошибки сети
    }
});

4.9. Response<T>

Сигнатура: public final class Response<T>

Что делает: Обертка для HTTP-ответа. Содержит код ответа (code()), заголовки (headers()), тело (body()), сообщение об ошибке (errorBody()) и информацию об успешности (isSuccessful()).

Пример:

if (response.isSuccessful()) {
    User user = response.body();
    System.out.println("Успех: " + user.getName());
} else {
    System.out.println("Ошибка HTTP: " + response.code());
    // Можно получить тело ошибки
    ResponseBody errorBody = response.errorBody();
}

4.10. Callback<T>

Сигнатура: public interface Callback<T>

Что делает: Интерфейс с двумя методами: onResponse() (вызывается при получении ответа от сервера, даже если код ошибки 4xx или 5xx) и onFailure() (вызывается при ошибке сети, таймауте или проблемах с парсингом).

Пример

Рекомендаций