Retrofit
Retrofit — це потужна бібліотека для Android і Java, яка спрощує взаємодію з REST API. Вона дозволяє вам легко працювати з HTTP-запитами, абстрагуючи низькорівневі деталі. Retrofit підтримує автоматичне перетворення JSON у Java-об'єкти за допомогою таких бібліотек, як Moshi, Gson або Jackson.
У цій статті ми розглянемо основи використання Retrofit у Java, найкращі практики та кроки для налаштування і створення запитів до REST API.
Залежності для Retrofit
Перед тим як почати, потрібно додати необхідні залежності у вашому проекті.
1. Додавання залежностей до build.gradle
У вашому файлі build.gradle додайте наступні залежності:
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0' // Основна бібліотека Retrofit
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // Конвертер для Gson
implementation 'com.squareup.okhttp3:okhttp:4.9.0' // OkHttp для роботи з HTTP
implementation 'com.squareup.moshi:moshi:1.12.0' // Можна використовувати Moshi для серіалізації
}
Налаштування Retrofit
1. Створення інтерфейсу API
Перше, що потрібно зробити, це визначити інтерфейс, який буде описувати ваші HTTP-запити. Для кожного ендпоінта API ви створюєте відповідний метод, який позначається за допомогою анотацій, таких як @GET, @POST, @PUT тощо.
Ось приклад:
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface ApiService {
@GET("posts")
Call<List<Post>> getPosts();
@GET("posts")
Call<List<Post>> getPostsByUserId(@Query("userId") int userId);
}
2. Створення Retrofit об'єкта
Далі необхідно налаштувати Retrofit, вказавши базовий URL для вашого API та конвертер для обробки JSON. Використаємо Gson для конвертації JSON у Java-об'єкти:
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClient {
private static Retrofit retrofit;
public static Retrofit getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl("https://jsonplaceholder.typicode.com/") // Базовий URL API
.addConverterFactory(GsonConverterFactory.create()) // Додаємо конвертер Gson
.build();
}
return retrofit;
}
}
3. Використання Retrofit для виконання запитів
Тепер ми можемо використовувати Retrofit для виконання запитів до API. Ось приклад того, як отримати список постів:
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class Main {
public static void main(String[] args) {
// Отримуємо інтерфейс API
ApiService apiService = RetrofitClient.getClient().create(ApiService.class);
// Виконуємо асинхронний запит для отримання постів
Call<List<Post>> call = apiService.getPosts();
call.enqueue(new Callback<List<Post>>() {
@Override
public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
if (response.isSuccessful()) {
List<Post> posts = response.body();
// Обробляємо список постів
for (Post post : posts) {
System.out.println(post.getTitle());
}
} else {
System.out.println("Запит не був успішним");
}
}
@Override
public void onFailure(Call<List<Post>> call, Throwable t) {
t.printStackTrace();
}
});
}
}
4. Синхронний запит
Якщо вам потрібно виконати запит синхронно (наприклад, в фоновому потоці), ви можете викликати метод execute():
try {
Response<List<Post>> response = call.execute();
if (response.isSuccessful()) {
List<Post> posts = response.body();
for (Post post : posts) {
System.out.println(post.getTitle());
}
} else {
System.out.println("Запит не був успішним");
}
} catch (IOException e) {
e.printStackTrace();
}
5. Моделювання відповіді
Ваші відповіді від API можуть бути різними. У Retrofit для обробки відповіді використовується Java-класи. Наприклад, для API https://jsonplaceholder.typicode.com/posts ви можете створити клас Post:
public class Post {
private int userId;
private int id;
private String title;
private String body;
// Гетери та сетери
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
Використання Retrofit для CRUD-операцій з JsonPlaceholder
Додаємо необхідні залежності в ваш файл build.gradle:
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0' // Основна бібліотека Retrofit
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // Конвертер для Gson
implementation 'com.squareup.okhttp3:okhttp:4.9.0' // OkHttp для роботи з HTTP
implementation 'com.squareup.moshi:moshi:1.12.0' // Moshi для серіалізації (опційно)
}
Структура проекту
- Моделі — клас, який описує структуру поста.
- API інтерфейс — визначення HTTP-запитів.
- Реалізація Retrofit — налаштування Retrofit.
- Діяльність або ViewModel — обробка запитів і відповіді.
1. Створення моделі даних (Post.java)
Ми створимо клас Post, що відображає дані поста.
public class Post {
private int userId;
private int id;
private String title;
private String body;
// Гетери та сетери
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
2. Створення інтерфейсу API (ApiService.java)
Визначаємо інтерфейс для всіх CRUD-операцій:
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.GET;
import retrofit2.http.PUT;
import retrofit2.http.POST;
import retrofit2.http.Path;
import java.util.List;
public interface ApiService {
// Отримати список всіх постів
@GET("posts")
Call<List<Post>> getPosts();
// Отримати пост за ID
@GET("posts/{id}")
Call<Post> getPostById(@Path("id") int id);
// Створити новий пост
@POST("posts")
Call<Post> createPost(@Body Post post);
// Оновити існуючий пост
@PUT("posts/{id}")
Call<Post> updatePost(@Path("id") int id, @Body Post post);
// Видалити пост
@DELETE("posts/{id}")
Call<Void> deletePost(@Path("id") int id);
}
3. Налаштування Retrofit (RetrofitClient.java)
Тепер налаштовуємо Retrofit:
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClient {
private static Retrofit retrofit;
private static final String BASE_URL = "https://jsonplaceholder.typicode.com/";
public static Retrofit getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) // Використовуємо Gson для конвертації
.build();
}
return retrofit;
}
}
4. Створення класу для роботи з API (Main.java)
Давайте створимо клас, який буде використовувати інтерфейс ApiService для виконання CRUD-операцій:
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import java.io.IOException;
import java.util.List;
public class Main {
public static void main(String[] args) {
ApiService apiService = RetrofitClient.getClient().create(ApiService.class);
// Операція GET: отримати всі пости
getAllPosts(apiService);
// Операція GET: отримати пост за ID
getPostById(apiService, 1);
// Операція POST: створити новий пост
createPost(apiService);
// Операція PUT: оновити пост
updatePost(apiService, 1);
// Операція DELETE: видалити пост
deletePost(apiService, 1);
}
// Отримати всі пости
private static void getAllPosts(ApiService apiService) {
Call<List<Post>> call = apiService.getPosts();
call.enqueue(new Callback<List<Post>>() {
@Override
public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
if (response.isSuccessful()) {
List<Post> posts = response.body();
posts.forEach(post -> System.out.println(post.getTitle()));
} else {
System.out.println("Запит не успішний!");
}
}
@Override
public void onFailure(Call<List<Post>> call, Throwable t) {
t.printStackTrace();
}
});
}
// Отримати пост за ID
private static void getPostById(ApiService apiService, int postId) {
Call<Post> call = apiService.getPostById(postId);
call.enqueue(new Callback<Post>() {
@Override
public void onResponse(Call<Post> call, Response<Post> response) {
if (response.isSuccessful()) {
Post post = response.body();
System.out.println("Post Title: " + post.getTitle());
} else {
System.out.println("Запит не успішний!");
}
}
@Override
public void onFailure(Call<Post> call, Throwable t) {
t.printStackTrace();
}
});
}
// Створити новий пост
private static void createPost(ApiService apiService) {
Post post = new Post();
post.setUserId(1);
post.setTitle("New Post Title");
post.setBody("This is the body of the new post.");
Call<Post> call = apiService.createPost(post);
call.enqueue(new Callback<Post>() {
@Override
public void onResponse(Call<Post> call, Response<Post> response) {
if (response.isSuccessful()) {
Post createdPost = response.body();
System.out.println("Created Post: " + createdPost.getTitle());
} else {
System.out.println("Запит не успішний!");
}
}
@Override
public void onFailure(Call<Post> call, Throwable t) {
t.printStackTrace();
}
});
}
// Оновити пост
private static void updatePost(ApiService apiService, int postId) {
Post post = new Post();
post.setTitle("Updated Post Title");
post.setBody("This is the updated body.");
Call<Post> call = apiService.updatePost(postId, post);
call.enqueue(new Callback<Post>() {
@Override
public void onResponse(Call<Post> call, Response<Post> response) {
if (response.isSuccessful()) {
Post updatedPost = response.body();
System.out.println("Updated Post: " + updatedPost.getTitle());
} else {
System.out.println("Запит не успішний!");
}
}
@Override
public void onFailure(Call<Post> call, Throwable t) {
t.printStackTrace();
}
});
}
// Видалити пост
private static void deletePost(ApiService apiService, int postId) {
Call<Void> call = apiService.deletePost(postId);
call.enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
System.out.println("Post deleted successfully");
} else {
System.out.println("Запит не успішний!");
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
t.printStackTrace();
}
});
}
}
:video-player{src="https://www.youtube.com/watch?v=GPP4hOTthRg"}