Обзор библиотеки Retrofit 2

retrofit_banner

На этом сайте уже публиковался обзор библиотеки Retrofit, однако с того времени она потеряла актуальность, т. к. синтаксис запросов сильно поменялся. Несмотря на это я советую прочитать первый обзор, чтобы понять базовые принципы работы с библиотекой.

Retrofit является одной из самых популярных Android-библиотек для создания HTTP-запросов. Популярность этой библиотеки объясняется простотой использования и высокой производительностью библиотеки.



Подключение библиотеки

Как обычно, прописываем зависимость в файле buld.gradle:

compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'

Т. к. библиотека находится на стадии beta, версия библиотеки может часто меняться, поэтому советую узнать последнюю версию библиотеки здесь.

Retrofit автоматически тянет с собой библиотеку OkHttp. Если у вас в зависимостях уже есть эта библиотека, то нужно исключить OkHttp из Retrofit:

compile ('com.squareup.retrofit2:retrofit:2.0.0-beta4') {  
  // exclude Retrofit’s OkHttp peer-dependency module and define your own module import
  exclude module: 'okhttp'
}
compile 'com.squareup.okhttp3:okhttp:3.0.0'

А вот так библиотека подключается через Maven:

<dependency>  
  <groupId>com.squareup.retrofit2</groupId>
  <artifactId>retrofit</artifactId>
  <version>2.0.0-beta4</version>
</dependency>  
<dependency>  
  <groupId>com.squareup.okhttp</groupId>
  <artifactId>okhttp</artifactId>
  <version>3.0.0</version>
</dependency>

Подключаем конвертеры

Retrofit не поставляется вместе с библиотекой GSON, поэтому мы должны прописать ее вручную:

compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'

RxJava

Если вы используете RxJava в своем приложении, не забудьте прописать данные зависимости:

compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'  
compile 'io.reactivex:rxandroid:1.0.1'

Синхронные и асинхронные запросы

Раньше, при использовании Retrofit 1.9 синхронный запрос объявлялся вот так:

/* Synchronous in Retrofit 1.9 */
 
public interface APIService {
 
    @POST("/list")
    Repo loadRepo();
 
}

А асинхронный запрос вот так:

/* Asynchronous in Retrofit 1.9 */
 
public interface APIService {
 
    @POST("/list")
    void loadRepo(Callback<Repo> cb);
 
}

В Retrofit 2.0 оба типа запросов имеют одинаковый вид:

import retrofit.Call;
 
/* Retrofit 2.0 */
 
public interface APIService {
 
    @POST("/list")
    Call<Repo> loadRepo();
 
}

Для синхронного запроса просто вызовите метод execute, а для асинхронного метод enqueue.

Делаем синхронный запрос

// Synchronous Call in Retrofit 2.0
 
Call<Repo> call = service.loadRepo();
Repo repo = call.execute();

Данный код должен вызываться в новом потоке, иначе приложение вылетит с ошибкой NetworkOnMainThreadException, т. к. запросы к сети в главном потоке запрещены. Для вызова метода execute используйте фоновые потоки.

Делаем асинхронный запрос

// Asynchronous Call in Retrofit 2.0
 
Call<Repo> call = service.loadRepo();
call.enqueue(new Callback<Repo>() {
    @Override
    public void onResponse(Response<Repo> response) {
        // Get result Repo from response.body()
    }
 
    @Override
    public void onFailure(Throwable t) {
 
    }
});

Код, представленный выше выполняет запрос в фоновом потоке, после в главном потоке вызывает метод onResponse или onFailure, в зависимости от результата. Для извлечения ответа от сервера используйте response.body().

Отмена запроса

Для отмены запроса используется метод cancel():

call.cancel();

Создание сервиса

В Retrofit 1.9 дополнение GsonConverter входило в пакет и автоматически инициализировался при создании RestAdapter. В Retrofit 2.0 нам нужно вручную подключать и инициализировать GsonConverter:

compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'

Конвертер добавляется с помощью метода addConverterFactory. Заметьте, что теперь RestAdapter называется Retrofit:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://api.nuuneoi.com/base/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();
 
service = retrofit.create(APIService.class);

Вот список официальных конвертеров, поддерживаемых Square:

  • Gson: com.squareup.retrofit:converter-gson
  • Jackson: com.squareup.retrofit:converter-jackson
  • Moshi: com.squareup.retrofit:converter-moshi
  • Protobuf: com.squareup.retrofit:converter-protobuf
  • Wire: com.squareup.retrofit:converter-wire
  • Simple XML: com.squareup.retrofit:converter-simplexml

Вы также можете создать свой конвертер, реализовав интерфейс Converter.Factory.

Кастомный GSON-объект

Если вы хотите изменить формат какого-нибудь JSON-объекта, то это можно сделать с помощью GsonConverterFactory.create():

Gson gson = new GsonBuilder()
        .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
        .create();
 
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://api.nuuneoi.com/base/")
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build();
 
service = retrofit.create(APIService.class);

Готово.

Новая концепция построения URL

Retrofit 2.0 предоставляет новую концепцию построения URL-запроса. Пожалуйста, взгляните на примеры ниже:

apiservice1 apiservice2 apiservice3

Как видно на скриншотах построение URL зависит от слешей, добавленных в базовом URL или в URL запроса.



В Retrofit 2.0 предлагается новый способ построения URL:

— Базовый URL: всегда заканчивается /
— @Url: НЕ начинается /

Например:

public interface APIService {
 
    @POST("user/list")
    Call<Users> loadUsers();
 
}
 
public void doSomething() {
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://api.nuuneoi.com/base/")
            .addConverterFactory(GsonConverterFactory.create())
            .build();
 
    APIService service = retrofit.create(APIService.class);
}

При вызове loadUsers будет сделан запрос на адрес http://api.nuuneoi.com/base/user/list.

Кроме того, в Retrofit 2.0 мы можем указать полный URL:

public interface APIService {
 
    @POST("http://api.nuuneoi.com/special/user/list")
    Call<Users> loadSpecialUsers();
 
}

При этом базовый URL будет проигнорирован.  Как видите в Retrofit 2.0 принцип построения URL существенно отличается оп предыдущих версий, поэтому не забудьте исправить URL-адреса в ваших проектах.

OkHttp стал обязательным

В Retrofit 1.9 библиотека OkHttp была необязательной. В Retrofit 2.0 OkHttp подключается автоматически, т. к. она прописана в зависимостях Retrofit.

onResponse вызывается даже при проблемах с ответом

Если после запроса Retrofit 1.9 не мог преобразовать ответ от сервера в объект, то вызывался метод Callback’а, сообщающего об ошибке (onFailure). Теперь же,  Retrofit 2.0 вызывает метод onResponse не зависимо от того, смогла она разобрать ответ или нет.

response

Метожы Response/Failure сильно различаются в Retrofit 1.9 и 2.0, поэтому будьте осторожны при переходе на новую версию.

Пропущенное разрешение для доступа в интернет вызывает SecurityException

В Retrofit 1.9 при пропуске разрешения для доступа в интернет, вызов асинхронной операции возвращал ошибку PERMISSION DENIED в Callback. В Retrofit 2.0 при пропуске разрешения выбрасывается исключение SecurityException.

sec

Это похоже на поведение при его использовании HttpURLConnection. В любом случае, не составляет никакого труда добавить разрешение на интернет в AndroidManifest.xml.

Заключение

Я думаю, что я осветил основные изменения в этой статье. Все изменения вы можете посмотреть в официальном ChangeLog’е. Начните использовать Retrofit 2 прямо сейчас. Тем более, документация на GitHub уже обновлена до версии Retrofit 2.0.

Комментарии:

7 комментариев

  1. Уведомление: Retrofit — библиотека для работы с REST API | Java-Help

  2. Антон Ответить

    Сколько читал про Retrofit, так и не увидел ни одного внятного примера синхронного запроса. Все пишут про новый поток, а как его по хорошему организовать?

      • Антон Ответить

        Если честно, то все как то очень сложно.
        Вот пример:
        Мне нужно осуществить запрос к API, но доступ к возвращаемым данным мне нужно не только в функции callback’e (то есть не в методе onResponse). Соответственно мне нужно делать синхронный запрос. А чтобы его сделать мне нужно создать поток, а для этого нужно подтащить в проект RxJava?
        Неужели нет методов попроще?

        • Admin АвторОтветить

          Ну тогда Chronos: habrahabr.ru/company/redmadrobot/blog/263111. Если уж совсем просто, то AsyncTasc или Thread.

  3. Ukrainelike Ответить

    Здравствуйте, подскажите новичку, если в запросе передається пароль, безопасно ли это? И как можна это сделать безопасней.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *