1. Обзор
Retrofit -это типобезопасный HTTP-клиент для Android и Java, разработанный Square ( Dagger , Okhttp ).
В этой статье мы объясним, как использовать Retrofit, уделив особое внимание его наиболее интересным функциям. В частности, мы обсудим синхронный и асинхронный API, как использовать его с аутентификацией, ведением журнала и некоторыми хорошими методами моделирования.
2. Настройка примера
Мы начнем с добавления библиотеки дооснащения и конвертера Gson:
com.squareup.retrofit2 retrofit 2.3.0 com.squareup.retrofit2 converter-gson 2.3.0
Для получения последних версий ознакомьтесь с Retrofit и converter-gson в центральном репозитории Maven.
3. Моделирование API
Модифицируйте модели конечных точек REST в качестве интерфейсов Java, делая их очень простыми для понимания и использования.
Мы смоделируем user API из GitHub; у этого есть конечная точка GET , которая возвращает это в формате JSON:
{ login: "mojombo", id: 1, url: "https://api.github.com/users/mojombo", ... }
Retrofit работает путем моделирования по базовому URL-адресу и путем создания интерфейсов, возвращающих сущности из конечной точки REST.
Для простоты мы собираемся взять небольшую часть JSON, смоделировав наш класс User , который будет принимать значения, когда мы их получим:
public class User { private String login; private long id; private String url; // ... // standard getters an setters }
Мы видим, что для этого примера мы берем только подмножество свойств. Retrofit не будет жаловаться на отсутствующие свойства – поскольку он отображает только то , что нам нужно , он даже не будет жаловаться, если мы добавим свойства, которых нет в JSON.
Теперь мы можем перейти к моделированию интерфейса и объяснить некоторые из аннотаций модернизации:
public interface UserService { @GET("/users") public Call> getUsers( @Query("per_page") int per_page, @Query("page") int page); @GET("/users/{username}") public Call
getUser(@Path("username") String username); }
Метаданных, предоставленных с аннотациями, достаточно для того, чтобы инструмент создавал рабочие реализации.
Аннотация @GET сообщает клиенту, какой метод HTTP использовать и на каком ресурсе, например, предоставляя базовый URL-адрес “https://api.github.com” он отправит запрос на “https://api.github.com/users”.
Ведущая “/” на нашем относительном URL-адресе говорит Retrofit, что это абсолютный путь на хосте.
Еще следует отметить, что мы используем совершенно необязательные параметры @Query , которые могут быть переданы как null, если они нам не нужны, инструмент позаботится об игнорировании этих параметров, если они не имеют значений.
И последнее, но не менее важное: @Path позволяет нам указать параметр path, который будет помещен вместо разметки, которую мы использовали в пути.
4. Синхронный/асинхронный API
Чтобы создать вызов HTTP-запроса, нам сначала нужно создать наш объект модернизации:
OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .client(httpClient.build()) .build();
Retrofit предоставляет удобный конструктор для строительства необходимого нам объекта. Ему нужен базовый URL – адрес, который будет использоваться для каждого вызова службы, и фабрика конвертеров , которая заботится о разборе данных, которые мы отправляем, а также о полученных ответах.
В этом примере мы будем использовать GsonConverterFactory , который сопоставит наши данные JSON с классом User , который мы определили ранее.
Важно отметить, что разные фабрики служат разным целям, поэтому имейте в виду, что мы также можем использовать фабрики для XML, прото-буферов или даже создать их для пользовательского протокола. Список уже реализованных фабрик мы можем посмотреть здесь .
Последняя зависимость – OkHttpClient – это клиент HTTP & HTTP/2 для приложений Android и Java. Это позаботится о подключении к серверу, отправке и извлечении информации. Мы также можем добавить заголовки и перехватчики для каждого вызова, которые мы увидим в нашем разделе аутентификации.
Теперь, когда у нас есть наш объект модернизации, мы можем построить наш вызов службы, давайте посмотрим, как сделать это синхронным способом:
UserService service = retrofit.create(UserService.class); CallcallSync = service.getUser("eugenp"); try { Response response = callSync.execute(); User user = response.body(); } catch (Exception ex) { ... }
Здесь мы можем увидеть, как Retrofit заботится о построении нашего интерфейса службы, вводя код, необходимый для выполнения запроса, на основе наших предыдущих аннотаций.
После этого мы получаем объект Call , который используется для выполнения запроса к API GitHub. Наиболее важным методом здесь является execute , который используется для выполнения
После успешного выполнения вызова мы можем получить тело ответа – уже на объекте пользователя – благодаря нашему GsonConverterFactory .
Сделать синхронный вызов очень просто, но обычно мы используем неблокирующий асинхронный запрос:
UserService service = retrofit.create(UserService.class); CallcallAsync = service.getUser("eugenp"); callAsync.enqueue(new Callback () { @Override public void onResponse(Call call, Response response) { User user = response.body(); } @Override public void onFailure(Call call, Throwable throwable) { System.out.println(throwable); } });
Теперь вместо метода execute мы используем метод enqueue , который принимает интерфейс Callback в качестве параметра для обработки успеха или неудачи запроса. Обратите внимание, что это будет выполняться в отдельном потоке.
После успешного завершения вызова мы можем получить тело так же, как и ранее.
5. Создание многоразового класса генератора услуг
Теперь, когда мы увидели, как построить наш объект модернизации и как использовать API, мы можем видеть, что мы не хотим продолжать писать конструктор снова и снова.
Нам нужен многоразовый класс, который позволит нам создать этот объект один раз и повторно использовать его в течение всего срока службы нашего приложения:
public class GitHubServiceGenerator { private static final String BASE_URL = "https://api.github.com/"; private static Retrofit.Builder builder = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()); private static Retrofit retrofit = builder.build(); private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); public staticS createService(ClassserviceClass) { return retrofit.create(serviceClass); } }
Вся логика создания объекта дооснащения теперь перенесена в этот класс GitHub Service Generator , что делает его устойчивым клиентским классом, который останавливает повторение кода.
Вот простой пример того, как его использовать:
UserService service = GitHubServiceGenerator.createService(UserService.class);
Теперь, если бы мы, например, создали службу репозитория , мы могли бы повторно использовать этот класс и упростить создание.
В следующем разделе мы расширим его и добавим возможности аутентификации.
6. Аутентификация
Большинство API-интерфейсов имеют некоторую аутентификацию для обеспечения доступа к нему.
Принимая во внимание наш предыдущий класс генератора, мы собираемся добавить метод create service, который принимает токен JWT с заголовком Authorization :
public staticS createService(ClassserviceClass, final String token ) { if ( token != null ) { httpClient.interceptors().clear(); httpClient.addInterceptor( chain -> { Request original = chain.request(); Request request = original.newBuilder() .header("Authorization", token) .build(); return chain.proceed(request); }); builder.client(httpClient.build()); retrofit = builder.build(); } return retrofit.create(serviceClass); }
Чтобы добавить заголовок к вашему запросу, нам нужно использовать возможности перехватчика OkHttp ; мы делаем это с помощью нашего ранее определенного конструктора и путем реконструкции объекта модернизации.
Обратите внимание, что это простой пример аутентификации, но с использованием перехватчиков мы можем использовать любую аутентификацию, такую как OAuth, пользователь/пароль и т. Д.
7. Ведение журнала
В этом разделе мы собираемся еще больше расширить наш генератор служб GitHub для ведения журнала возможностей, которые очень важны для целей отладки в каждом проекте.
Мы собираемся использовать наши предыдущие знания о перехватчиках, но нам нужна дополнительная зависимость, которая является HttpLoggingInterceptor от OkHttp, давайте добавим ее в наш pom.xml :
com.squareup.okhttp3 logging-interceptor 3.9.0
Теперь давайте расширим наш Генератор сервисов GitHub класс:
public class GitHubServiceGenerator { private static final String BASE_URL = "https://api.github.com/"; private static Retrofit.Builder builder = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()); private static Retrofit retrofit = builder.build(); private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); private static HttpLoggingInterceptor logging = new HttpLoggingInterceptor() .setLevel(HttpLoggingInterceptor.Level.BASIC); public staticS createService(ClassserviceClass) { if (!httpClient.interceptors().contains(logging)) { httpClient.addInterceptor(logging); builder.client(httpClient.build()); retrofit = builder.build(); } return retrofit.create(serviceClass); } public staticS createService(ClassserviceClass, final String token) { if (token != null) { httpClient.interceptors().clear(); httpClient.addInterceptor( chain -> { Request original = chain.request(); Request.Builder builder1 = original.newBuilder() .header("Authorization", token); Request request = builder1.build(); return chain.proceed(request); }); builder.client(httpClient.build()); retrofit = builder.build(); } return retrofit.create(serviceClass); } }
Это окончательная форма нашего класса, мы можем видеть , как мы добавили HttpLoggingInterceptor , и мы установили его для базового ведения журнала, который будет регистрировать время, необходимое для выполнения запроса, конечную точку, статус для каждого запроса и т. Д.
Важно взглянуть на то, как мы проверяем, существует ли перехватчик, чтобы случайно не добавить его дважды.
8. Заключение
В этом обширном руководстве мы рассмотрели превосходную библиотеку модернизации, сосредоточив внимание на ее API синхронизации/асинхронности, некоторых лучших практиках моделирования, аутентификации и ведения журнала.
Библиотека может использоваться очень сложными и полезными способами; для расширенного использования с RxJava, пожалуйста, ознакомьтесь с этим учебником .
И, как всегда, исходный код можно найти на GitHub .