понедельник, 26 мая 2014 г.

Третья встреча Kiev Android Dev Club

Прошло уже чуть больше недели с тех пор как произошла третья сходка Kiev Android Dev Club и я понял, что пришло время написать по ней отчет ;)

В этот раз героем дня был Retrofit, ибо он играл более или менее значительную роль во всех 4 докладах. Вообще, как-то так сложилось, что мы не сговариваясь сделали встречу посвященную написанию клиентов для REST API.


Первый доклад - Loaders

Это был мой доклад и в нем я популяризировал Loader'ы. Помнится, больше года назад на GDD 2013 это было главной холивор темой, которая вдохновила Борю организовать сходку андроид-девов, поэтому нужно было вернуться к истокам и поговорить о ней подробнее. Я готовил этот доклад из эгоистических побуждений: хотелось составить в голове общую картину того, кто такие лоадеры и зачем их стоит использовать. А потому доклад у меня получился длинный - прошу прощения, если кто подустал его слушать ;) Начал я его с обзора средств для работы с асинхронными процессами, ну а закончил примером реализации небольшого лоадера, который посредством Retrofit'а обращался к Github API.


Конечно, лоадеры это спорная тема и есть мнение, что они призваны решать одну единственную задачу (курсоры грузить), с которой они справляются блестяще. Мне кажется, что они вполне могут решать и другие задачи, к примеру, делать небольшие запросы к REST API. В чем, я думаю, сходятся все, так это в том, что у лоадеров несколько запутанный жизненный цикл. Мне совершенно не понятно, почему нельзя было сделать базовый класс, в котором нужно было переопределить только один метод (в AsyncTaskLoder переопределения одного метода совершенно недостаточно, хотя он там один абстрактный) - думаю это значительно бы повысило популярность этого инструмента. Но поживем увидим - может в следующих версиях API их прокачают или предложат нечто принципиально новое.

Самым полезным из моей презентации я считаю слайд с источниками - если вы заинтересовались темой лоадеров, то они вам наверняка помогут. Выдеру их из презентации и приведу здесь:
  • Серия статей про Loaders (by Alex Lockwood) - совершенно замечательная серия статей, рассказывающая о том, как люди жили до лоадеров, зачем лоадеры появились и как написать свой. Кстати, в нем приводится тот же пример, что и в официальной андроид доке, но с более подробными комментариями и без багов реализации (хотя, может уже и в доке поправили, не знаю)
  • Android networking without pain (презентация) - презентация о средствах для работы с удаленным API. Хороший обзор.
  • Modern techniques for implementing REST clients on Android 4.0 and below
  • CWAC-LoaderEx and Failed Abstractions - пример испозования лоадера для работы с REST API. Прямой конкурент моему примеру, но несколько более функциональный (а от того и большой).
  • Android tutorial to learn through small projects (оно на китайском) - пример собственного лоадера, правда на китайском языке. Это первоисточник монструозной sequence диаграммы жизненного цикла лоадера.
  • Пример на GitHub - мой пример.
В общем, как по мне, лоадеры это тема, как минимум, достойная пристального внимания.

Второй доклад - полезняшки от Stanfy

Второй доклад делал Рома Мазур и рассказывал он о инструментах, которые мы используем в Stanfy для создания приложений, которые лезут в сеть. Его презентация была вовсе не презентацией, а сеансом live coding'а. Краткий пересказ: как-то раз в начале нового проекта Рома понял, что вот прямо щас ему нужно будет наклепать заготовку для работы с удаленным API. Поскольку раз этот был далеко не первый, а Рома - хороший программист, то у него сработал условный рефлекс "нужно-срочно-автоматизировать-это" (говорят, что если вы делаете что-то одинаковое больше 3 раз подряд и у вас этот рефлекс не срабатывает, то это повод начать беспокоиться). В идеале, нужен был инструмент, с помощью которого можно было:

  • описать API (в машинно-понятном формате) и документировать его (в человеко-читабельном формате). В совсем идеальном мире API вообще описывается только в одном месте и это место - гелиумовская спека. Но для этого нужно, чтоб серверная команда эту спеку писала изначально.
  • протестировать его
  • сгенерировать максимум кода, который можно из этого описания сгенерировать (классы моделей для тел запросов и ответов, классы для совершения этих самых запросов и т.д.)
Но быстро сказка сказывается, да не быстро дело делается и с первого захода получилась штука, на которой можно описать API, сгенерировать автоматизированные тесты для него и сварганить классы моделей. Хотя к текущему моменту из вышеприведенного списка осталось только генерацию документации запилить. Штука называется Helium, является предметно-ориентированным языком (DSL) на основе Groovy. Мы действительно ей пользуемся и даже заставили это делать нашу серверную команду. Юзкейс примерно такой:

  1. получаете на руки описание API
  2. описываете его на Helium. После этого Helium сам сгенерирует простейшие тесты (в виде "отправить составленный по описанию запрос" -> "сервер должен ответить, что все хорошо" + "структура ответа полностью соответствует описанию")
  3. по желанию, пишете более сложные сценарии тестов: например, нужно чтоб пользователь зарегистрировался у вас на сервере и после этого смог сделать заказ чего-нибудь. Делаете запрос на регистрацию, потом запрос на добавление заказа, проверяете что нигде не было фейлов.
  4. генерируете POJO классы для моделей запросов
  5. по желанию генерируете Retrofit-интерфейс для запросов
  6. шарите файл с описанием своей серверной команде и делаете регулярно запускаемую задачку с тестами где-то на дженкинсе
  7. когда у вас с сервером какие-то спорные вопросы - тыкаете их носом в результаты тестов
Весьма эффективный сценарий, я вам скажу.
Но эти самые запросы к API нужно где-то выполнять, причем точно не в UI-потоке. Для этих целей у нас есть Goro. Это инструмент для создания последовательных асинхронных очередей задач. По сути, обертка над пулом очередей. Но, есть несколько важных преимуществ:

  • по умолчанию, в качестве пула потоков используется пул асинк тасков, что есть хорошо в андроид реальности
  • очереди именованные и последовательность выполнения задач гарантирована
  • нет строгого соответствия очередей и потоков, на которых выполняются задачи из этих очередей. Вообще, работа с потоками полностью от нас скрыта и это делает все проще для конечного пользователя (то есть, нас с вами)
  • наконец, можно запускать Goro в контексте сервиса и не боятся, что ваше приложение будет убито в то время, когда оно находится в фоне (ибо приложение у которого есть работающие сервисы весьма высоко Андроидом ценятся и убиваются значительно реже собратьев без оных)
Goro мне очень нравится. Это классная штука, поскольку вы можете использовать ее прямо из коробки, а цели ее вполне ясны. Настоящий Unix-way.
Еще про эту штуку есть статья в нашем корпоративном блоге.


Но использовать Goro в одиночестве это не так просто, ведь активности, как вы помните, не вечны - нужно как-то переживать смену конфигурации. Здесь нам на помощь приходит Async - обертка над Loader'ами, которая облегчает работу с ними до безобразия (настолько, что вы никогда и не узнаете, что под капотом у них эти самые лоадеры). Проблема: вам нужен инструмент, который позволит вам выполнить какую-то работу в фоне и получить результат в активности. Решение: вы создаете класс с методом, который нужно исполнить в фоне (класс имплементирует Callable), в активности создаете метод, который фоновый процесс должен запустить и аннотируете его. Async генерирует для вас класс Operator, в котором вы устанавливаете обработчики успешного запроса и ошибки. Все, запрос готов и можно не париться о обработке смены конфигурации.

Пример использования всего этого можно найти вот тут.

Важное замечание: если вам понравились Stanfy-полезняшки и вы хотели бы попробовать их в деле - обязательно сделайте это, но помните, что все эти штуки находятся в стадии разработки и их архитектура/способ использования/функциональность может значительно поменяться. Это инструменты, которые реально используются в проектах, а потому и постоянно меняются. В любом случае, все это open source и вы вольны распоряжаться им как пожелаете, а если вам чего-то не хватает - дописать это ;)

Третий доклад - Retorfit

Этот доклад делал Антон Минашкин и делал он его про Retrofit. Кажется, что после третьей нашей встречи поголовно все знают, что же это такое :) Но если вдруг не знаете, то вот презентацию посмотрите:


Вкратце, это штука, которая генерит для вас все для работы с удаленным API. Выглядит это так:
  1. вы создаете обычный Java интерфейс, где для каждого API endpoint содаете по методо (с параметрами, которые этому endpoint должны быть переданы)
  2. аннотируете эти методы (какой метод (GET, POST, PUT, DELETE...) должен быть использован, какие хедеры, какие из параметров должны пойти в тело, а какие прямо в адрес и т.д.)
  3. создаете экземпляр Retrofit и просите у него создать реализацию вашего интерфейса
  4. пользуетесь полученным экземпляром
  5. PROFIT!!!
Все крайне просто и от этого круто! Более того, эта штука очень гибкая и вы можете в нем заменить практически все что угодно: не нравится Gson для маппинга - замените его на Jackson, не нравится HttpClient - замените его на OkHttp и так еще можно долго продолжать. Это реально крутая вещь! А во второй версии, по словам Антона, она станет еще круче.

Кстати, это прямой конкурент гугловской Volley. В прочем, есть статья где сравниваются эти две библиотеки и Retrofit там выигрывает.

Четвертый доклад - Continuous integration

Последний доклад делал Антон Голуб, но презентацией пока не поделился. К сожалению, я мало запомнил из этой презентации, кроме того, что Jenkins сейчас de facto стандарт и остальные, даже платные, альтернативы не очень-то у него выигрывают. Как только у меня появится презентация я ее сюда добавлю, но а пока все.

Надеюсь вы не померли от скуки дочитав аж до этого места ;) Спасибо за внимание и до новых встреч!

Комментариев нет: