Переход с Retrofit 1 на Retrofit 2

Введение

Библиотека Retrofit версии 2 наконец-то вышла в марте 2016 года. В Retrofit 2 включено множество фундаментальных изменений, ломающих совместимость с первой версией. Это означает, что вы должны обновить свой код, имеющий отношение к Retrofit, при обновлении до Retrofit 2.

Зависимости Gradle

Retrofit доступен в виде зависимости Maven или Gradle. При использовании Retrofit 1, вам приходилось так же включать в зависимости и используемые им библиотеки более низкого уровня. Retofit 2 же по умолчанию использует OkHttp, который уже включен в его зависимости.

Итак, чтобы использовать Retrofit 2, вам нужно включить в build.gradle следующую строчку:

Если же вы не хотите использовать OkHttp той версии, которая поставляется вместе с Retrofit 2, вы можете исключить ее из зависимостей, и подключить желаемую версию:

Важно: по умолчанию в Retrofit 2 не включен GSON. Его нужно добавить отдельной зависимостью. Кроме того, придется вручную указать его как конвертер:

RestAdapter -> Retrofit

Ранее при создании Api вы взаимодействовали с классом RestAdapter. Теперь он называется Retrofit:

setEndpoint —> baseUrl

В Retrofit 1 базовый URL задавался методом setEndpoint():

Теперь этот метод заменен методом baseUrl():

Обратите внимание: вы обязательно должны задать базовый URL, прежде чем вызывать метод build().

Обработка базового URL

В Retrofit 2 обработка URL происходит совершенно иначе. Очень важно понимать это, прежде чем обновляться с Retrofit 1 до Retrofit 2!

Ранее, заданный базовый URL всегда использовался как URL по умолчанию для запросов. В декларируемом вами индивидуальным URL в интерфейсе для API вы задавали частичные пути, включающие параметры query или path, тело запроса или multipart.

При запросе базовый URL и индивидуальный URL объединялись в финальный URL, по которому отправлялся запрос. Чтобы проиллюстрировать это, давайте рассмотрим следующий пример:

Retrofit 1 просто объединял части URL, и в Retrofit 2 это поведение было изменено. Теперь финальный URL создается при помощи метода HttpUrl.resolve(), который создает ссылки, очень похожие на известный <a href>

Давайте посмотрим на пример:

Да, как вы видите, слэш в начале второй части URL затер часть /v2, т.е. Retrofit 2 при построении URL при наличии слэша в начале URL считает, что мы обращаемся к корню. Если же мы уберем этот слэш, то все встанет на свои места:

Итого: используйте относительные URL при определении пути метода, и указывайте слэш в конце базового URL.

Динамические URL

Динамические URL — это тот случай, для которого сложно сходу придумать применение. Однако, мы можем привести пример, с которым мы столкнулись при реализации одного из наших приложений. Например, мы хотим скачать ZIP-файл, который располагается по постоянно меняющемуся адресу. Файл может храниться, например, на Amazon S3, или еще где-либо. Проблема была в том, что RestAdapter каждый раз, когда мы хотели скачать файл, должен был создаваться с новым базовым URL. Это лишняя головная боль, потому что для каждого запроса создается новый клиент HTTP, и это определенно плохая практика.

К счастью, с приходом Retrofit 2 время боли закончилось, и теперь мы можем использовать динамические URL. Теперь можно оставить аннотацию с HTTP методом пустой, и задать URL с использованием аннотации @Url при помощи параметра:

Interceptors из OkHttp

Интерцепторы — это мощный способ кастомизации запросами в Retrofit. Эта возможность была полезна в Retrofit 1, и будет полезной в Retrofit 2. Популярный способ использования — когда вы хотите перехватить запрос и, к примеру, добавить свои заголовки. К примеру, вы хотите передать авторизационный токен в заголовоке Authorization.

Так как Retrofit глубоко интегрирован с OkHttp, вам будет нужно кастомизировать OkHttpClient и добавить Interceptor. В следующем примере мы перехватим запрос и добавим заголовки Authorization и Accept:

Если вы используете кастомный OkHttpClient, вам будет нужно задать клиент в Retrofit.Builder, используя метод client(). Таким образом вы замените стандартный клиент своей дополненной версией.

Вы можете использовать интерцепторы для различных задач, таких как аутентификация, логгирование, для различных манипуляций с запросами и ответами, и т.д.

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

Если вы работали с Retrofit 1, вам знакомы различные методы объявления интерфейса сервиса. Синхронные методы обязывали задавать возвращаемый тип. Асинхронные же методы обязывали использовать Generic Callback в качестве последнего параметра.

В Retrofit 2 больше нет различий между синхронными и асинхронными запросами при объявлении интерфейса. Теперь каждый метод должен возвращать Generic Call, в котором указывается желаемый тип ответа.

Объявление интерфейса:

Как видите, больше нет разделения на синхронные и асинхронные запросы при объявлении интерфейса.

Выполнение запроса

Retrofit 1 обрабатывал выполнение запроса, основываясь либо на возвращаемом типе, либо на параметре Callback:

В Retrofit 2 же запрос выполняется совсем иначе. Так как запрос теперь оборачивается в объект Call, вы можете использовать метод call.execute() для синхронного выполнения, либо call.enqueue(new Callback<>() {}) для асинхронного:

В Retrofit 2 метод onResponse() вызывается даже тогда, когда запрос завершился с HTTP ошибкой. В классе Response присутствует метод isSuccessful(), позволяющий проверить, был ли запрос совершен успешно (т.е. относится ли код ответа к множеству  кодов 2xx). Если код ответа отличается от 2xx, то вам нужно будет обработать ошибку самостоятельно.

Если вы хотите обрабатывать тело ответа даже в случае HTTP ошибки (например, чтобы получить детали ошибки), вы можете использовать метод errorBody() класса ResponseBody.

Внимание: если вы используете синхронные запросы, выполняйте их не на UI потоке. Иначе ваше приложение упадет.

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

В Retrofit 1 вы не могли отменить запрос, даже если он еще не начал выполняться. В Retrofit 2 вы можете отменить запрос в любое время:

Не важно, выполняете вы синхронный или асинхронный запрос, OkHttp не отправит его, если вы успеете быстро его отменить.

Без конвертера по умолчанию

В Retrofit 1 по умолчанию использовался конвертер GSON для парсинга JSON ответов. В Retrofit 2 дефолтного конвертера больше нет. Вам нужно задать конвертер самостоятельно в зависимостях build.gradle и при создании Api. Пример для GSON:

Доступно несколько конвертеров:

  • Gson: com.squareup.retrofit2:converter-gson:2.1.0
  • Moshi: com.squareup.retrofit2:converter-moshi:2.1.0
  • Jackson: com.squareup.retrofit2:converter-jackson:2.1.0
  • SimpleXML: com.squareup.retrofit2:converter-simplexml:2.1.0
  • Protobuf: com.squareup.retrofit2:converter-protobuf:2.1.0
  • Wire: com.squareup.retrofit2:converter-wire:2.1.0

Если ни один из представленных конвертеров вам не подходит, вы можете создать свой, имплементировав абстрактный класс Converter.Factory. Если вам нужна помощь, посмотрите на исходный код имеющихся конвертеров: https://github.com/square/retrofit/tree/master/retrofit-converters

Добавление конвертера в Retrofit

В Retrofit 2 вы должны вручную указать конвертер, который будет использоваться. Конвертеров может быть несколько:

В этом примере мы добавили два конвертера. Порядок добавления конвертеров важен! Давайте представим сценарий, который показывает важность порядка добавления. Т.к. ответ в Protobuf может быть обернут в JSON, Retrofit попробует распарсить ответ с использованием Gson, если тот был указан первым в списке. Но мы хотим, чтобы ответ сначала пробовал распарситься при помощи конвертера Protobuf, и лишь при неудаче он будет передан следующему конвертеру.

Без логгирования по умолчанию

Плохие новости: в Retrofit 2 по умолчанию нет логгирования. Однако, вы можете реализовать логгирование при помощи кастомного интерцептора.

WebSockets в Retrofit 2.1

В связи с тем, что слой HTTP был полностью удален из Retrofit 2 и перенесен в OkHttp, имеется возможность использования WebSocket’ов через OkHttp.

Подробнее можете посмотреть здесь: https://github.com/square/okhttp/tree/master/okhttp-ws

Обратите внимание: эта фича является экспериментальной!

Заключение

Эта статья — обширный обзор значимых изменений в Retrofit 2 по сравнению с Retrofit 1, которые требуют вашего внимания и изменения кода. Вы можете посмотреть все изменения каждого релиза в официальном ченджлоге: https://github.com/square/retrofit/blob/master/CHANGELOG.md. Если вас интересует какая-то конкретная фича, вы можете попробовать найти ее там.

Наслаждайтесь переходом на Retrofit 2! Мы считаем, что все изменения были хорошо продуманы и подняли Retrofit на новый уровень.

Эта статья является переводом. Источник: https://futurestud.io/blog/retrofit-2-upgrade-guide-from-1-9


Мы постоянно добавляем новые статьи! Чтобы ничего не пропустить, подпишитесь на нашу группу ВКонтакте, или на рассылку по e-mail (обещаем, спама не будет. честно.)

GET YOUR EMAIL UPDATES

We send out our lovely email newsletter with useful tips and techniques, recent articles and upcoming events. Thousands of readers have signed up already. Get a free WordPress eBook now.
E-Mail