Android studio что такое retrofit

Retrofit

Многие сайты имеют собственные API для удобного доступа к своим данным. На данный момент самый распространённый вариант — это JSON. Также могут встречаться данные в виде XML и других форматов.

Библиотека Retrofit упрощает взаимодействие с REST API сайта, беря на себя часть рутинной работы.

Авторами библиотеки Retrofit являются разработчики из компании «Square», которые написали множество полезных библиотек, например, Picasso, Okhttp, Otto.

Библиотекой удобно пользоваться для запроса к различным веб-сервисам с командами GET, POST, PUT, DELETE. Может работать в асинхронном режиме, что избавляет от лишнего кода.

В основном вам придётся работать с методами GET и POST. Если вы будет создавать собственный API, то будете использовать и другие команды.

В Retrofit 2.x автоматически подключается библиотека OkHttp и её не нужно прописывать отдельно.

Библиотека может работать с GSON и XML, используя специальные конвертеры, которые следует указать отдельно.

Затем в коде конвертер добавляется с помощью метода addConverterFactory().

Список готовых конвертеров:

  • Gson: com.squareup.retrofit2:converter-gson
  • Jackson: com.squareup.retrofit2:converter-jackson
  • Moshi: com.squareup.retrofit2:converter-moshi
  • Protobuf: com.squareup.retrofit2:converter-protobuf
  • Wire: com.squareup.retrofit2:converter-wire
  • Simple XML: com.squareup.retrofit2:converter-simplexml
  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

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

Можно подключить несколько конвертеров (порядок важен).

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

Базовый URL всегда заканчивается слешем /. Задаётся в методе baseUrl().

Можно указать полный URL в запросе, тогда базовый URL будет проигнорирован:

Для работы с Retrofit понадобятся три класса.

  1. POJO (Plain Old Java Object) или Model Class — json-ответ от сервера нужно реализовать как модель
  2. Retrofit — класс для обработки результатов. Ему нужно указать базовый адрес в методе baseUrl()
  3. Interface — интерфейс для управления адресом, используя команды GET, POST и т.д.

Работу с Retrofit можно разбить на отдельные задачи.

Задача первая. POJO

Задача первая — посмотреть на структуру ответа сайта в виде JSON (или других форматов) и создать на его основе Java-класс в виде POJO.

POJO удобнее создавать с помощью готовых веб-сервисов в автоматическом режиме. Либо можете самостоятельно создать класс, если структура не слишком сложная.

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

Задача вторая. Интерфейс

Задача вторая — создать интерфейс и указать имя метода. Добавить необходимые параметры, если они требуются.

В интерфейсе задаются команды-запросы для сервера. Команда комбинируется с базовым адресом сайта (baseUrl()) и получается полный путь к странице. Код может быть простым и сложным. Можно посмотреть примеры в документации.

Запросы размещаются в обобщённом классе Call с указанием желаемого типа.

В большинстве случаев вы будете возвращать объект Call с нужным типом, например, Call . Если вас не интересует тип ответа, то можете указать Call .

Здесь также используются аннотации, но уже от самой библиотеки.

С помощью аннотации указываются веб-команды, а затем Java-метод. Для динамических параметров используются фигурные скобки (users//repos), в которые подставляются нужные значения.

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

Аннотации

Аннотация Описание
@GET() GET-запрос для базового адреса. Также можно указать параметры в скобках
@POST() POST-запрос для базового адреса. Также можно указать параметры в скобках
@Path Переменная для замещения конечной точки, например, username подставится в в адресе конечной точки
@Query Задаёт имя ключа запроса со значением параметра
@Body Используется в POST-вызовах (из Java-объекта в JSON-строку)
@Header Задаёт заголовок со значением параметра
@Headers Задаёт все заголовки вместе
@Multipart Используется при загрузке файлов или изображений
@FormUrlEncoded Используется при использовании пары «имя/значение» в POST-запросах
@FieldMap Используется при использовании пары «имя/значение» в POST-запросах
@Url Для поддержки динамических адресов

@Query

Аннотация @Query полезна при запросах с параметрами. Допустим, у сайте есть дополнительный параметр к запросу, который выводит список элементов в отсортированном виде: http://example.com/api/v1/products/cats?sort=desc. Это несложный пример и мы можем поместить запрос с параметром в интерфейс без изменений.

Если не требуется управлять сортировкой, то её можно оставить в коде и она будет применяться по умолчанию. Но в нашем запросе есть ещё один параметр, который отвечает за категорию котов (домашние, уличные, породистые), которая может меняться в зависимости от логики приложения. Этот параметр можно снабдить аннотацией и программно управлять в коде.

Сортировку мы оставляем как есть, а категорию перенесли в параметры метода под именем categoryId, снабдив аннотацией, с которой параметр будет обращаться на сервер в составе запроса.

Запрос получится в виде http://example.com/api/v1/products/cats?sort=desc&category=5.

В одном методе можно указать несколько Query-параметров.

Запрос может иметь изменяемые части пути. Посмотрите на один из примеров запроса для GitHub: /users/:username. Вместо :username следует подставлять конкретные имена пользователей (https://api.github.com/users/alexanderklimov). В таких случаях используют фигурные скобки в запросе, в самоме методе через аннотацию @Path указывается имя, которое будет подставляться в путь.

@Headers

Пример аннотации @Headers, которая позволяет указать все заголовки вместе.

@Multipart

Пример аннотации @Multipart при загрузке файлов или картинок:

@FormUrlEncoded

Пример использования аннотации @FormUrlEncoded:

Пример аннотации @Url:

Задача третья. Retrofit

Для синхронного запроса используйте метод Call.execute(), для асинхронного — метод Call.enqueue().

Объект для запроса к серверу создаётся в простейшем случае следующим образом

В итоге мы получили объект Retrofit, содержащий базовый URL и способность преобразовывать JSON-данные с помощью указанного конвертера Gson.

Далее в его методе create() указываем наш класс интерфейса с запросами к сайту.

После этого мы получаем объект Call и вызываем метод enqueue() (для асинхронного вызова) и создаём для него Callback. Запрос будет выполнен в отдельном потоке, а результат придет в Callback в main-потоке.

В результате библиотека Retrofit сделает запрос, получит ответ и производёт разбор ответа, раскладывая по полочкам данные. Вам остаётся только вызывать нужные методы класса-модели для извлечения данных.

Основная часть работы происходит в onResponse(), ошибки выводятся в onFailure() (неправильный адрес сервера, некорректные формат данных, неправильный формат класса-модели и т.п). HTTP-коды сервера (например, 404) не относятся к ошибкам.

Метод onResponse() вызывается всегда, даже если запрос был неуспешным. Класс Response имеет удобный метод isSuccessful() для успешной обработки запроса (коды 200хх). В ошибочных ситуациях вы можете обработать ошибку в методе errorBody() класса ResponseBody.

Другие полезные методы Response.

  • code() — HTTP-код ответа
  • body() — сам ответ в виде строки, без сериализации
  • headers() — HTTP-заголовки
  • message() — HTTP-статус (или null)
  • raw() — сырой HTTP-ответ

Можно написать такую конструкцию.

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

Перехватчики (Interceptors)

В библиотеку можно внедрить перехватчики для изменения заголовков при помощи класса Interceptor из OkHttp. Сначала следует создать объект перехватчика и передать его в OkHttp, который в свою очередь следует явно подключить в Retrofit.Builder через метод client().

Поддержка перехватчиков/interceptors для обработки заголовков запросов, например, для работы с токенами авторизации в заголовке Authorization.

HttpLoggingInterceptor

Библиотека HttpLoggingInterceptor является частью OkHttp, но поставляется отдельно от неё. Перехватчик следует использовать в том случае, когда вам действительно нужно изучать логи ответов сервера. По сути библиотека является сетевым аналогом привычного LogCat.

Подключаем перехватчик к веб-клиенту. Добавляйте его после других перехватчиков, чтобы ловить все сообщения. Существует несколько уровней перехвата данных: NONE, BASIC, HEADERS, BODY. Последний вариант самый информативный, пользуйтесь им осторожно. При больших потоках данных информация забьёт весь экран. Используйте промежуточные варианты.

RxJava

Сами разработчики библиотеки очень любят реактивное программирование и приложили многие усилия для интеграции с библиотекой RxJava.

Источник

Как в Android получить данные с сервера с помощью Retrofit

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

Предположим, что на каком-то сервере есть данные. И сервер готов нам выдать эти данные. Чаще всего для этого используется формат json. Вот пример таких данных: https://rawgit.com/startandroid/data/master/messages/messages1.json

Давайте используем Retrofit, чтобы получить в приложении данные из этого файла.

Для начала немного теории.

Конфигурирование Retrofit можно разделить на две части: API интерфейс и билдер. Давайте рассмотрим подробно, кто из них за что отвечает.

Представим себе работу по обмену данными приложения с сервером. Как это происходит? Обычно сервер предоставляет нам какое-то API, т.е. набор методов (он же REST). Если, например, это сервер интернет-магазина, то его API может содержать следующие методы:
getProducts — получить список товаров
getProdut — получить детальные данные о продукте
getOrders — получить список заказов
getOrder — получить детальные данные о заказе
createOrder — создать заказ
и т.д.

Это серверные методы и, чтобы их вызывать, нам необходимо выполнять запросы, которые могут выглядеть, например, так:
http://server/api/v1/getProducts
http://server/api/v1/getProduct
http://server/api/v1/getOrders
http://server/api/v1/getOrder
http://server/api/v1/createOrder
и т.д.

Т.е. у сервера есть какой-то базовый URL — http://server/api/v1/. И к нему просто добавляются имена методов (getProducts, getOrders, и т.д.), чтобы получать ссылки для работы с API методами.

Возвращаемся в приложение. Было бы очень удобно, если бы у нас в приложении был класс ServerApi с методами getProducts, getOrders и т.д. И при вызове этих методов происходил бы вызов соответствующих серверных методов. И Retrofit как раз может создать для нас такой класс. От нас потребуется интерфейс, в котором мы распишем необходимые методы.

Вот пример такого интерфейса:

Этот код немного упрощен. В реальном примере будут дополнительные аннотации и обертки. Но общий смысл он вполне передает. Retrofit создаст класс, который реализует этот интерфейс. Внутри этого класса и будут сгенерированы вызовы к серверу.

А мы в этом интерфейсе можем настроить названия методов и некоторые HTTP штуки, такие как передаваемые параметры (Query), заголовки (Header) и т.п.

Рассмотрим описание метода getProducts подробнее:

Аннотация GET означает, что HTTP-запрос для getProducts должен быть типа GET. А в качестве параметра для этой аннотации нам необходимо указать имя метода на сервере. Обратите внимание, что здесь не фигурирует базовый URL (http://server/api/v1/). Его мы будем указывать позже, в билдере.

— это тип возвращаемых данных. Retrofit сам сможет сконвертировать json данные в список объектов Product. Подробнее об этом тоже поговорим во время обсуждения билдера.

Ну и имя метода — getProducts(). В этом примере оно совпадает с именем метода на сервере. Но это необязательно. Т.е. вы вполне можете сделать так

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

Переходим к практике. Чтобы использовать в вашем проекте Retrofit, в build.gradle файле, в секции dependencies добавляйте зависимости:

Первая строка — это непосредственно Retrofit, а вторая — это его Gson-конвертер.

Она вернет нам json данные, которые представляют из себя список сообщений. Каждое сообщение содержит поля id, time, text и иногда image. Эта ссылка, конечно, не API, а просто текстовый файл, но смысл остается тем же, просто вместо имени метода у нас будет имя файла.

Мы делим ссылку на две части:
«https://rawgit.com/startandroid/data/master/messages/» — базовый URL (будет указан в билдере)
«messages1.json» — имя файла (будет указано в интерфейсе, в GET аннотации)

Мы можем создать интерфейс для работы с этой ссылкой. Там будет только один метод, и он будет возвращать List .

Давайте сначала создадим класс Message.

Его поля соответствуют полям в данных в messages1.json.

Теперь создаем интерфейс:

В аннотации GET указываем, что к базовому URL надо будет добавить «messages1.json», чтобы получилась нужная нам ссылка.

Обратите внимание на Call. Эта обертка нужна для работы Retrofit. В ней мы указываем, какой тип данных ожидаем получить из messages1.json — т.е. List .

Интерфейс создан, теперь переходим к билдеру:

В билдере мы указываем базовый URL и добавляем Gson конвертер, чтобы Retrofit сам смог сконвертировать json данные в объекты Message. Это минимум настроек, который от нас требуется для нашего простого примера. Для сложных случаев количество параметров может быть больше.

В итоге у нас есть объект Retrofit, который содержит базовый URL и способность преобразовывать json данные с помощью Gson. Мы передаем ему в метод create класс интерфейса, в котором описывали методы.

И получаем реализацию MessagesApi от Retrofit. В этой реализации соединены настройки билдера (базовый URL и Gson конвертер) и описания методов из интерфейса (метод messages для получения файла messages1.json). В итоге Retrofit будет брать базовый URL из билдера, присоединять к нему остаток пути, который мы указываем в GET в интерфейсе, и тем самым получит полную ссылку.

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

1) У интернет-магазина есть два сервера: рабочий (с реальными данными) и тестовый. На обоих развернуто одинаковое API. И есть приложение, которое общается с сервером. Debug-версия приложения должна работать с тестовым сервером и выводить в лог всю информацию об этом. Release-версия работает с рабочим сервером и ничего не выводит в лог.

Эту разницу между Debug и Release версиями можно реализовать двумя разными билдерами. Просто указываем для них разные базовые URL и разные настройки логирования. А интерфейс в обоих случаях будет использоваться один и тот же.

2) Есть сервер с API. И есть приложение, которое вызывает эти методы. На сервере реализована авторизация. Т.е. приложение должно вызвать метод авторизации, получить токен, и затем использовать этот токен при вызове некоторых API методов, которые связаны с пользователем.

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

В этом случае можно создать два билдера. Первый не будет использовать токен. Реализацию, полученную от этого билдера используем для работы с методами, не требующими токена. А второй билдер будет добавлять токен ко всем вызовам. Реализацию, полученную от этого билдера используем для всех методов, где нужен токен.

Итак, связка интерфейса и билдера дала нам реализацию MessagesApi. Используем ее для получения данных. Вызываем метод messages()

Метод log — это просто вывод в лог текста

Вызов метода messages вернет нам Call объект. При выполнении этого кода запрос к серверу еще не был отправлен. Call дает нам возможность отправить запрос синхронно (блокируя текущий поток) или асинхронно (с колбэком). Мы выбираем асинхронный вариант: вызываем метод enqueue и создаем для него Callback. Запрос будет выполнен в отдельном потоке, а результат придет в Callback в main потоке.

Если взаимодействие с сервером пройдет успешно, то мы получим результат в метод onResponse в объекте Response. Чтобы добраться до данных, необходимо вызвать метод body() у Response объекта. Это даст нам список сообщений — List . Выводим в лог количество записей в этом списке.

Запустив этот код, мы получим список из 50 записей. Лог покажет следующее:

Если по каким-то причинам не удалось достучаться до сервера, то вместо onResponse, будет вызван метод onFailure. Добавим вывод в лог ошибки, которую вернет нам Retrofit

Чтобы эмулировать ошибку, мы можем просто поломать имя сервера в базовом URL, который задается в билдере. Например, добавим букву r к rawgit:

https://rrawgit.com/startandroid/data/master/messages/

Запускаем и видим в логе ошибку.

failure java.net.UnknownHostException: Unable to resolve host «rrawgit.com»: No address associated with hostname

Retrofit сообщает, что не нашел сервер rrawgit.com

Если случится какая-то ошибка в процессе работы Retrofit, то она попадет также в onFailure. Например, если сервер вернет некорректные данные, то GsonConverterFactory не сможет их распарсить и выкинет ошибку. А Retrofit отправит ее нам в onFailure.

Есть тип ошибок, который Retrofit умеет обрабатывать без вызова onFailure. Это HTTP-ошибки сервера. Самый простой случай — ошибка 404. Запрос дойдет до сервера, но сервер вместо данных вернет HTTP 404 Not found. Казалось бы — это ошибка и на должна прийти в onFailure. Но нет. onFailure вызывается в случае, когда не удалось достучаться до сервера. А здесь с сервером все ок, он просто вместо данных вернул нам информацию о том, что мы странные и хотим непонятного.

В итоге, ответ сервера мы получим в методе onResponse. И нам надо как-то различать, вернул сервер данные или ошибку. Для этого у объекта Response есть метод isSuccessful.

Перепишем метод onResponse

Если запрос был выполнен успешно (isSuccessfull), то выводим в лог количество полученных записей. Иначе выводим в лог код ошибки.

Снова поменяем базовый URL, чтобы спровоцировать ошибку 404. Добавим лишнюю букву s в слово messages:

https://rawgit.com/startandroid/data/master/messagess/

Запускаем и в логе видим

response code 404

Чтобы получить полный текст ошибки сервера, используйте

Приведу весь код работы с Retrofit:

Разумеется, вам не нужно при каждом запросе к серверу использовать билдер и создавать новый объект MessagesApi. Это делается один раз за время работы приложения и далее объект MessagesApi используется везде, где необходима работа с сервером. Для реализации Singleton подойдет Dagger или любая другая реализация этого паттерна.

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

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Читайте также:  Самый лучший офлайн переводчик для андроид
Оцените статью