Полезное для Android разработчика, Retrofit Часть 1

в 10:23, , рубрики: android, Square, библиотеки, Разработка под android, самая лучшая компания, хочу в square

На этой недели дайджест не простой и посвещен он компании Square Inc, которая разрабатывает удобные библиотеки, которые во многом облегчают нам работу в повседневном программировании :)

Retrofit

Превращает REST API сервис в Java Interface
Пример:

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

Для работы необходим RestAdapter, который сгенерирует код взаимодействия с вашим интерфейсом.

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("https://api.github.com")
    .build();

GitHubService service = restAdapter.create(GitHubService.class);

И теперь в при каждом вызове сгенерированного GitHubService будет посылать HTTP запрос на сервер

List<Repo> repos = service.listRepos("octocat");

Используйте аннотации для описания ваших HTTP запросов

  • Подстановка в URL параметров, и поддержка запросов
  • Превращение объекта в тело запроса(JSON, Protocol buffers)
  • Мульти запросы объектов и передача файлов

Описание API

Аннотации в ваших методах интерфейса и параметрах помогут сформировать более точный запрос

Методы запросов

Каждый метод HTTP запроса должен быть аннотирован, для построения отностильной ссылки на сервер, Реализованно 5 методов аннотаций
GET, POST, PUT, DELETE и HEAD. Ссылка будет сконструированна взависимости от вашей аннотации

@GET("/users/list")

Вы также можете легко создавать запросы примиком из аннотаций

@GET("/users/list?sort=desc")

Манипуляция с ссылками

Ссылка на запрос может быть динамичной, используйте подстановочные блоки и параметры в методах. Подстановочные блоки это строки которые обернуты в фигурные скобки, пример: {id}, и переменная которая должна подставить должна быть аннотированна Path

@GET("/group/{id}/users")
List<User> groupList(@Path("id") int groupId);

Также можно и создавать запросы

@GET("/group/{id}/users")
List<User> groupList(@Path("id") int groupId, @Query("sort") String sort);

Для отправки множественных запросов используйте аннотацию Map

@GET("/group/{id}/users")
List<User> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);

Запросы с объектами

Вы также можете отправлять объекты в тело HTTP запроса с помощью аннотации Body

@POST("/users/new")
void createUser(@Body User user, Callback<User> cb);

Ваш объект будет сконвертированов созданным вами RestAdapter'ским конвертатором (о как перевел я)

Отправка форм

Ваши методы могут быть объявлены для перекодирования и отправки ввиде формы
Запросы в форме отправляются с помощью @FormUrlEncoded аннотацией
и каждое поле формы должно быть аннотированно @Field ом

@FormUrlEncoded
@POST("/user/edit")
User updateUser(@Field("first_name") String first, @Field("last_name") String last);

Multipart(не знаю как перевсти) запросы должны быть аннотированы с помощью @Multipart

@Multipart
@PUT("/user/photo")
User updateUser(@Part("photo") TypedFile photo, @Part("description") TypedString description);

Манипуляция с заголовками

Вы также можете управлять заголовками вашего запроса используя Header

@Headers("Cache-Control: max-age=640000")
@GET("/widget/list")
List<Widget> widgetList();
@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("/users/{username}")
User getUser(@Path("username") String username);

Примечание* заголвки не переписываются, Все заголвки с таким же имененм будут включены в запрос.

Запросы с Загловком могут быть обновлены динамически используя все тот же Header, строка может быть включена в заголовок если она не является Null объектом

@GET("/user")
void getUser(@Header("Authorization") String authorization, Callback<User> callback)

Заголовки которые должны быть включены в каждый запрос могут быть транслированны в RequestInterceptor, Следующий код создает RequestInterceptor который добавляет User-Agent в каждый запрос

RequestInterceptor requestInterceptor = new RequestInterceptor() {
  @Override
  public void intercept(RequestFacade request) {
    request.addHeader("User-Agent", "Retrofit-Sample-App");
  }
};

RestAdapter restAdapter = new RestAdapter.Builder()
  .setEndpoint("https://api.github.com")
  .setRequestInterceptor(requestInterceptor)
  .build();

Синхронный vs Асинхронные vs Observable

Ваши методы могут быть задеклорированны для синхронной и асихрнной отправки.

Ниже приведенный метод будет вызван синхронной отправкой

@GET("/user/{id}/photo")
Photo getUserPhoto(@Path("id") int id);

Теперь асинхронный

@GET("/user/{id}/photo")
void getUserPhoto(@Path("id") int id, Callback<Photo> cb);

Разница в том что асинхронный метод должен имнеть в конце Callback и ничего не возвращать
В андроиде Callback'и будут вызваны в UI потоке.

Retrofit также интегрирован с RxJava для поддержки rx.Observable

@GET("/user/{id}/photo")
Observable<Photo> getUserPhoto(@Path("id") int id);

Observable запросы посылаются асинхронно, а также просматриваются в в том же потоке, что и HTTP запросы, для обработки в разных потоках используйте вызовите метод observerOn(Scheduler) в возвращенном Observable

Обработка ответов

HTTP ответы могут автоматически сконвертироваться в указонный объект, используется RestAdapter'овский GSON ковертор. Указать объект вы можете при возвращении, Сallback или Observable

@GET("/users/list")
List<User> userList();

@GET("/users/list")
void userList(Callback<List<User>> cb);

@GET("/users/list")
Observable<List<User>> userList();

Для получения доступка к необработанному ответу выполните следующее

@GET("/users/list")
Response userList();

@GET("/users/list")
void userList(Callback<Response> cb);

@GET("/users/list")
Observable<Response> userList();

Конфигурация RestAdapter

Вы также можете настроить ваш RestAdapter, сбив настройки по умолчанию ;)

Настройка JSON конвертора

Retrofit использует по умолчанию GSON библиотеку для обработки JSON ответов или объектов в тело HTTP запроса, Вы всегда можете настроить его под свои нужды

Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    .registerTypeAdapter(Date.class, new DateTypeAdapter())
    .create();

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("https://api.github.com")
    .setConverter(new GsonConverter(gson))
    .build();

GitHubService service = restAdapter.create(GitHubService.class);

Каждый ответ обрабатывается указанным в RestAdapter конвертором

Обработка нестандартных форматов

По умолчанию Retrofit конвертирует только Json. Но также и имеются простые реализации обработки XML, для полного ознакомления взгляните на спиок Retorfit-конверторов
Теперь простая реализация XML конвертора

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("https://api.soundcloud.com")
    .setConverter(new SimpleXMLConverter())
    .build();

SoundCloudService service = restAdapter.create(SoundCloudService.class);

Обработка ошбок

Если вам нужен свой обработчик ошибок, предусматривают свою реализацию класса ErrorHandler, Ниже приведенны код показывает как обрабатывать ошибки, когда в HTTP запросе произошла 401 ошибка

class MyErrorHandler implements ErrorHandler {
  @Override public Throwable handleError(RetrofitError cause) {
    Response r = cause.getResponse();
    if (r != null && r.getStatus() == 401) {
      return new UnauthorizedException(cause);
    }
    return cause;
  }
}

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("https://api.github.com")
    .setErrorHandler(new MyErrorHandler())
    .build();

Спасибо всем за внимания ;)

Музыка при переводе:
Lights & Motion — The March
Craig Wazbinski & R.wali Vincent — Sideways
The Family Crest — Make Me a Boat
Ruth Barrett — Earthflow
Ludovico Einaudi — Divenire
Aron Wright — In the woods
Earth Wind and Fire — September
Anywayican — Walk The Moon

А какую музыку слушаете вы?

Автор: 03uk

Источник

Поделиться