Использование Retrofit в вашем Android приложении

Использование Retrofit в вашем Android приложении
mangohost

В прошлой статье мы получали данные о пользователях GitHub с помощью AsyncTask и HTTP клиента который присутствовал по умолчанию. В этой статье мы рассмотрим библиотеку, которая упростит для нас  работу с API. Эту библиотеку разработала хорошо известная в кругах Java разработчиков, компания Square, а называется эта библиотека Retrofit. Текущая версия библиотеки 2.0. Страничка библиотеки http://square.github.io/retrofit/

 

Добавление зависимостей:

Создаем новый проект, и добавляем в Gradle следующие зависимости:

  • Retrofit - собственно сама библиотека, с помощью которой мы будем осуществлять запросы к API.
  • okhttp - это HTTP-клиент от все той же компании Square, который  делает HTTP запросы, устанавливает заголовки и т.д.
  • converter-gson - используется в Retrofit, чтобы преобразовывать HTTP ответы в Java объекты.

Ниже приведен пример, как это должно выглядеть в  Gradle файле:

compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'   
compile 'com.squareup.okhttp:okhttp:2.4.0'   
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta4'

Описываем POJO класс эквивалентный JSON объекту:

POJO (Plain Old Java Object) - это простой Java объект который ни от чего не наследуется, и не реализует интерфейсов. Подробней на Википедии.

Мы будем получать данные о Github пользователе например обо мне https://api.github.com/users/ZapevalovAnton. Вот такой JSON мы получим в итоге:

{
    "login": "ZapevalovAnton",
    "id": 6674242,
    "avatar_url": "https://avatars.githubusercontent.com/u/6674242?v=3",
    "gravatar_id": "",
    "url": "https://api.github.com/users/ZapevalovAnton",
    "html_url": "https://github.com/ZapevalovAnton",
    "followers_url": "https://api.github.com/users/ZapevalovAnton/followers",
    "following_url": "https://api.github.com/users/ZapevalovAnton/following{/other_user}",
    "gists_url": "https://api.github.com/users/ZapevalovAnton/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/ZapevalovAnton/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/ZapevalovAnton/subscriptions",
    "organizations_url": "https://api.github.com/users/ZapevalovAnton/orgs",
    "repos_url": "https://api.github.com/users/ZapevalovAnton/repos",
    "events_url": "https://api.github.com/users/ZapevalovAnton/events{/privacy}",
    "received_events_url": "https://api.github.com/users/ZapevalovAnton/received_events",
    "type": "User",
    "site_admin": false,
    "name": "ZapevalovAnton",
    "company": null,
    "blog": "http://recipebook.su",
    "location": null,
    "email": null,
    "hireable": null,
    "bio": null,
    "public_repos": 0,
    "public_gists": 0,
    "followers": 1,
    "following": 0,
    "created_at": "2014-02-13T16:57:54Z",
    "updated_at": "2016-02-14T11:47:21Z"
}

Для начала нам нужно описать Java POJO класс, эквивалентный такому JSON'у. Так как мы люди ленивые, руками мы ничего описывать не будем, а воспользуемся специальным сервисом-генератором http://www.jsonschema2pojo.org/. Копируем наш JSON в текстовое поле этого сервиса. Пишем имя вашего пакета, название класса "GithubUser". "Source Type" выбираем "JSON", "Annotation style" выбираем "Gson" и ставим галочку "Include getters and setters". После этого нажимаем на кнопку "Zip", под текстовым полем, дожидаемся ссылки на скачивание, и скачиваем класс.

Настройка Retrofit:

Переходим к самому интересному. Создаем интерфейс GithubAPI в папке Вашего проекта, и описываем в нем запросы, которые вам необходимы. В нашем примере  мы просто будем получать данные о пользователе, поэтому я опишу всего один запрос (Endpoint):

public interface GitApiInterface {

    @GET("/users/{username}")
    Call<GithubUser> getUser(@Path("username") String username);

    // Another endpoints...
}

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

У всех таких Endpoint'ов есть аннотация в виде HTTP метода (GET, POST, PUT, DELETE и т.д.). После аннотации мы объявляем метод, в который пробрасываем тип возвращаемых данных, то есть тип того, что должен возвращать этот метод, в нашем случае это GithubUser. В параметрах самого метода мы указываем, то что мы хотим передавать в запрос, в нашем случае это username, который мы сначала указали в фигурных скобках в строке запроса, а потом передали в функцию в виде аннотации @Path.

Стоит обратить внимание на то, что GET параметры запроса передаются немного другим способом, их не нужно указывать в строке запроса, а просто нужно передать их методу с аннотацией @Query, например:

@GET("/search/users") 
Call <GithubUser> searchUser(@Query ("q") String name) ;

По сути Retrofit - это класс, которые превращает наш интерфейс c описанными запросами к API, в вызываемые объекты. Разумеется Retrofit нужно инициализировать. В самом простом случае это выглядело бы вот так:

private String BASE_URL = "https://api.github.com" ;  

Retrofit client = new Retrofit.Builder()  
                    .baseUrl(BASE_URL)
                    .build();

То есть, мы объявляем базовый URL, на основе которого будут строится запросы, и инициализируем сам Retrofit. Но для нашего примера, этого маловато, так как мы хотим, чтобы наши запросы магическим образом превращались из простого JSON в JAVA объекты, поэтому давайте поговорим о конверторах.

Конверторы:

Из коробки Retrofit, умеет конвертировать HTTP ответ в okhttp ResponseBody, а нам остается превратить его в Java объект. В настоящее время Retrofit поддерживает 6 разных конверторов, в принципе мы можем использовать любой из них:

  • 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-gson, поэтому нам нужно добавить сам конвертер в инициализацию Retrofit перед, тем как вызываем метод .build() . Теперь будет возвращаться Java объект.

private String BASE_URL = "https://api.github.com" ;  

Retrofit client = new Retrofit.Builder()  
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

Запросы к API:

Как и в предыдущей статье нам нужно добавить разрешение для доступа в интернет, перед тегом <application>, в наш AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

Открываем MainActivity.java файл. Вызывать методы GithubAPI, будем в методе oncreate() нашей activity (Инициализацию Retrofit, которая описана выше, я тоже поместил в этот метод).

GithubAPI service = client.create(GithubAPI.class);  
Call<GithubUser> call = service.getUser("ZapevalovAnton");  

call.enqueue(new Callback<GithubUser>() {  
     @Override
     public void onResponse(Response<GithubUser> response) {
         if (response.isSuccess()) {
             // request successful (status code 200, 201)
             GitResult result = response.body();
         } else {                   
              //request not successful (like 400,401,403 etc)
              //Handle errors
         }
     }

     @Override
     public void onFailure(Throwable t) {

     }
});

Это пример асинхронного запроса, для синхронного запроса, нужно использовать метод execute() , который будет возвращать данные. Если запрос будет успешно выполнен, то в переменной result, будет объект с данными  о пользователе, обращать к которым нужно через так называемые getter'ы и setter'ы.

Заключение:

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

Комментарии

28 июня 2016 17:55
Azamat Murzagalin

Why did u use GitResult instead of GitHubUser in response callback? What is this GitResult class?

30 июня 2016 09:54
Администратор

Sorry, of course it is my typo. I corrected the article. Thank you for comment.

8 августа 2016 15:28
Gadzhi S

Тут не все параметры указаны при вызове public void onResponse(Response response) { И тут опечатка isSuccessful надо вместо isSuccess

7 июля 2017 00:33
Сергей

Статья полное дерьмо. Нет полного кода классов. Это необходимо для понимания новичкам. Более подробно с полным кодом и разбором загрузки XML читайте тут: http://www.vogella.com/tutorials/Retrofit/article.html

20 июля 2017 21:07
Администратор

Да, статья конечно простая. Ещё раз повторюсь, что это перевод. Но так критично отзываться о чужом труде, по крайней мере, не этично. На хабре бы уже давно прилетело НЛО, затёрло бы Ваш коммент и забанило бы Вашу учётную запись. Хотя откуда Вам знать, скорей всего с таким подходом, Вас просто не пускают на Хабр) Статья на Vogella, конечно более полная, но на тот момент, когда я занимался переводом этой статьи, я бы просто напросто не осилил статью с Vogella.

20 июля 2017 10:51
Саха

слизали с хабра...и то не все вот полная статья https://habrahabr.ru/post/314028/

20 июля 2017 20:58
Администратор

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

26 февраля 2018 21:00
Алексей

Спасибо за статью, Антон! В наше время очень много неблагодарных людей, которые конкретно так зажрались :) Не обращайте внимания.

mangohost