Если есть задача написать клиент для работы с Restful сервером, не знаю существует ли удобнее и функциональнее бибилотеки, чем Retrofit. Эта открытая бибилиотека от компании Square в основном поддерживается хорошим человеком Jake Wharton.

Раньше приходилось писать свои велисопеды для работы с сервером с использованием HttpUrlConnection, HttpClinet, выделять дополнительные потоки, парсить ответы и потом передавать все в главный поток, при этом все усложнялось разнообразием запросов https, http, post, get и т.д.

Описание API в коде

Начать работать с этой библиотекой очень просто. Берем наше API сервера и используя аннотацию Retrofit, описываем в интерфейсах

public interface GitHubService {  
  @GET("/users/{user}/repos")  
  Call<List<Repo>> listRepos(@Path("user") String user);  
}

Тут мы описываем GET запрос по адресу /users/{user}/repos (общий для всех запросов домен url указывается в другом месте) причем адрес зависит от перменной user, которую мы передадим в метод. @Path("user") мы указываем, что данную перемнную мы используем в url запроса.

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

Можно api разделить на разные интерйесы для удобства использования например: для авторизации, для работы с пользователем и т.д.

Создание сервиса для работы с API

Теперь, чтобы пользоваться нашими API интерфейсом на необходимо создать RestAdapter и сервис

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("garmax.co")
                .build();

Тут мы в setEndpoint указываем общую часть URL для всех запросов.

GitHubService apiService = retrofit.create(GitHubService.class);

Передаем класс нашего интерфейса, вот мы и создали сервис для работы с нашим API.

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

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

Начиная с версии 2.0 все результаты методов в retrofit оборачиваются в Call. Этот класс хранит в себе все данные запроса, мы можем повторить запрос, при не удачной попытке, либо вызывая метод clone выполнять один и тот же запрос несколько раз. Так же можно отменить запрос в любой момент вызвав метод cancel класса Call. В предыдущих версиях, что бы указать как будет выполнятся запрос синхронно или асинхронно необходимо было по-разному описывать методы, либо метод должен был возвращать не void тип, либо передавать callback для асинхронного выполнения. С помощью нововведения Call мы можем описать один раз метод, но вызывать по-разному в коде:

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

Call<List<Repo>> call = apiService.listRepos("garmax");
List<Repo> list = call.execute().body();

Асинхронное выполнение запроса

Call<List<Repo>> call = apiService.listRepos("garmax");
call.enqueue(new Callback<List<Repo>>() {  
    @Override
    public void onResponse(Response<List<Repo>> response, Retrofit retrofit) {
        if (response.isSuccess()) {
            // Запрос выполнился успешно
        } else {
            // Сервер вернул ошибку
        }
    }

    @Override
    public void onFailure(Throwable t) {
        // Произошла ошибка при выполненни запроса
    }
}

Еще один огромный плюс retorfit это то, что он из коробки работает с RxJava

public interface GitHubService {  
  @GET("/users/{user}/repos")  
  Observable<List<Repo>> listRepos(@Path("user") String user);  
}

Обработка ошибок Тут тоже все замечательно.

При асинхронном выполнении в callback вызывается метод onFailure, подробности можно получить из аргумента Throwable.

В синхронных запросах необходимо перехватывать исключения RetrofitError

try {
    List<Repo> list = call.execute().body();
} catch(RetrofitError error) {
    // Обрабатываем ошибку
}

Загрузка файла

Так же можно загружать файлы на сервер POST запросом.

Вместе с файлом будем передавать ещё и его описание. Наш интерфейс будет выглядеть так:

@Multipart
@POST("/upload")
Call<UploadFileResponse> upload(@Part("description") RequestBody fileDescription, @Part MultipartBody.Part file);

Дальше в коде вызываем наш метод:

File myFile = ,,,;

RequestBody bodyDescription = RequestBody.create(MediaType.parse("multipart/form-data"), "My file");

RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), myFile);
MultipartBody.Part bodyFile = MultipartBody.Part.createFormData("file", myFile.getName(), requestFile);

apiService.upload(bodyDescription, bodyFile)

Плюсы

  • Очень простой и гибкий способ описать API в коде
  • Выполнение запросов асинхронно и синхронно
  • Совместимость с RxJava
  • Кастомизация: можно выбрать разные библиотеки для выполнения запросов и парсинга ответов разных форматов, вплоть до написания своих.
  • Простота при обработке ошибок

Минусы

До версии 2 были неудобные моменты, но в новой версии их исправили. Поэтому добавляем retrofit к проекту и наслаждаемся разработкой клиентских приложений.

Предыдущий Следующий

Blog Comments powered by Disqus.