На этой недели дайджест не простой и посвещен он компании 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