В прошлой статье мы получали данные о пользователях 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 - это мощная библиотека, которая значительно упрощает жизнь разработчикам и избавляет от писанины кучи лишнего кода. Документация очень сухая (хоть в ней вроде и есть все необходимое), а русскоязычных статей по ней очень мало.
Комментарии
Why did u use GitResult instead of GitHubUser in response callback? What is this GitResult class?
Sorry, of course it is my typo. I corrected the article. Thank you for comment.
Тут не все параметры указаны при вызове public void onResponse(Response response) { И тут опечатка isSuccessful надо вместо isSuccess
Статья полное дерьмо. Нет полного кода классов. Это необходимо для понимания новичкам. Более подробно с полным кодом и разбором загрузки XML читайте тут: http://www.vogella.com/tutorials/Retrofit/article.html
Да, статья конечно простая. Ещё раз повторюсь, что это перевод. Но так критично отзываться о чужом труде, по крайней мере, не этично. На хабре бы уже давно прилетело НЛО, затёрло бы Ваш коммент и забанило бы Вашу учётную запись. Хотя откуда Вам знать, скорей всего с таким подходом, Вас просто не пускают на Хабр) Статья на Vogella, конечно более полная, но на тот момент, когда я занимался переводом этой статьи, я бы просто напросто не осилил статью с Vogella.
слизали с хабра...и то не все вот полная статья https://habrahabr.ru/post/314028/
Если бы вы были повнимательней, то увидели, что перевод здесь появился ещё в феврале 2016 года, в то время как на хабре он появился значительно позже) К сожалению, в то время я не оставлял ссылки на переводы и не так тщательно выбирал контент. Но сейчас, я стараюсь переводить действительно интересные материалы, чтобы такие как вы молодцы хоть чему то учились)
Спасибо за статью, Антон! В наше время очень много неблагодарных людей, которые конкретно так зажрались :) Не обращайте внимания.