Содержание статьи
Google I/O
Jetpack
На конференции Google I/O много говорили о Jetpack — своего рода прокачанном наборе инструментов, который сама Google рекомендует использовать для создания быстрых, производительных, эффективных и самых-самых в мире приложений.
В целом инструменты достаточно стандартны, это все те же набившие оскомину AppCompat, новомодный Android KTX (кстати, да, Google намекает, что Java пора на покой), компоненты так называемой архитектуры Android: LiveData, ViewModel, Room и так далее. В списке есть и стандартные API Android, такие, например, как менеджер загрузок, а еще Emoji, куда же без них.
Запутав за десять лет экосистему Android до такой степени, что среднестатистический разработчик уже не может понять, куда ему ткнуться, Google решила все-таки внести ясность.
Xakep #230. Социальная инженерия
WorkManager
Среди компонентов Jetpack оказался один новый и довольно занятный. Название ему — WorkManager, а история очень и очень интересная. Издревле в Android было два основных метода выполнить фоновую работу: фоновый поток (AsyncTask, например) и сервисы. Последние пользовались особой популярностью, потому как работали независимо от самого приложения, да еще и с возможностью попросить систему о своем перезапуске.
Когда набежала толпа гоблинов, вирусов и говнокодеров, стало ясно, что так дело не пойдет и нужен более контролируемый системой фоновый механизм. Google придумала JobScheduler, подсистему Android 5, которая позволяла отдать системе задачу на выполнение в такое-то и такое-то время, почти как в iOS. Сервисы тем временем неистово подавлялись (а в Android 8 вообще ушли в нелегал).
Со временем JobScheduler обрастал функциональностью, появился его аналог для более старых ОС (Firebase JobDispatcher), а народ все не унимался: ну неудобно нам, убогим, первые версии JobScheduler не работали, другие постоянно менялись, предлагаемая Google альтернатива зависела от самой инфраструктуры Google; плюс у нас тут RxJava и вообще реактивщина, а вы нам какой-то JobScheduler с его идеями из прошлого века.
Вот Google и решила выкатить свой WorkManager с промайзами и обсерверами. Если говорить в двух словах, то WorkManager — это работающая на костях существующего Android библиотека, которая позволяет тебе делать любые фоновые штуки с реактивщиной в нужное тебе время, нужной последовательности и нужных условиях и вообще не заботиться о том, на какой версии все это будет работать (библиотека выберет нужный механизм сама, в зависимости от версии Android).
WorkManager.getInstance().beginWith(firstWork)
.then(secondWork)
.then(thirdWork)
.enqueue()
Android App Bundle
Еще один важнейший анонс, сделанный компанией на Google I/O, — это App Bundle (видео), мечта всех домохозяек, взявших Android Studio в руки. Представь, что у тебя есть приложение, в которое понапихано множество самой разной графики в разных разрешениях, поддержка 150 языков, а еще есть сборки нативных библиотек для четырех архитектур.
Чтобы поддерживать все это дело, тебе приходится писать большой build.gradle, который собирал бы для тебя с десяток различных вариантов APK для разных платформ, разрешений экрана, возможно даже языков. Все это пришлось бы отдельно заливать в Play Store (ну ладно, может быть, ты юзаешь devops). В любом случае возни море, а все ради того, чтобы размер APK для каждого устройства и региона был адекватным.
А теперь представь, что ты просто нажимаешь «Собрать приложение» и вместо множества пакетов Android Studio выдает тебе один большой файл формата AAB. И в нем все: все картинки, шрифты, изображения, сборки библиотек — все, что только можно. Ты заливаешь этот файл в Google Play, и на этом твои проблемы заканчиваются: Google Play сам разберет его на множество мелких APK под разные архитектуры, размеры экрана и регионы.
Более того, в данный момент Google тестирует функцию Dynamic feature modules — с ее помощью можно разбивать базовый APK на части, которые будут докачиваться при необходимости. Ну правда, зачем тебе все приложение, если большей частью его функций ты даже не будешь пользоваться?
AndroidX
Ну и в конце, конечно же, об AndroidX. Команда разработчиков support-библиотек, нужных для реализации новых функций ОС на старых устройствах, уже, кажется, сама запуталась и решила привести в порядок все эти com.android.support:appcompat-v7, support-v4 и прочий ворох невнятных, никак не связанных между собой имен.
Теперь у нас есть единое пространство имен для всех библиотек поддержки: androidx
. Все, что относится к API самого Android, теперь в пакете android
, внешние гугловские библиотеки поддержки — в androidx
. Было:
android.support.**
android.databinding.**
android.arch.**
android.arch.persistence.room.**
Стало:
androidx.@
androidx.databinding.@
androidx.room.@
Посмотреть
Как Android отрисовывает картинку
Drawn out: how Android renders (Google I/O ’18) — интересное видео с рассказом о системе рендеринга Android. Основная цель — донести до зрителя идею, что малейшие строчки их кода и малейшие изменения интерфейса приводят в движение огромные механизмы и это следует иметь в виду. Простые примеры:
- простейшее окошко со списком состоит из более чем десятка лейаутов;
- простая операция смены цвета элемента приводит к его полной инвалидации, то есть пересчету состояния и размеров элемента, а кроме того, изменению информации обо всех предках этого элемента;
- затем эта информация должна быть синхронизирована с потоком отрисовки, работающим с GPU, плюс ему должны быть отданы битмапы;
- затем список необходимых для отрисовки операций перестраивается с целью их оптимизации на GPU (на видео есть превосходный пример на тему отрисовки Gmail в разных вариантах);
- с помощью GL-команд выполняется отрисовка нужного изображения, которое затем возвращается обратно в тред отрисовки;
- затем в дело вступает SurfaceFlinger, который собирает все части интерфейса Android в единое целое.
И это всего лишь то, что происходит при нажатии на элемент списка. В видео также есть рассказ о происходящем во время промотки этого списка. Рекомендую посмотреть.
Оптимизация Android P
What’s new in Android Runtime (Google I/O ’18) — еще одно отличное выступление на Google I/O, посвященное оптимизациям в среде исполнения Android P. Выступление касается трех пунктов:
- Kotlin;
- память;
- облачные профили.
С Kotlin все оказалось довольно просто, докладчики рассказали о вынесении null-проверок в вызывающие функции, оптимизациях циклов и некоторых других вещей.
Две остальные части доклада куда интереснее. Во-первых, CompactDex — специальный компактный формат исполняемого файла Dex (в нем хранится код приложений для Android). В Android P формат CompactDex используется для хранения извлеченного из APK кода приложения, а также для хранения кода приложения в оперативной памяти.
В среднем CompactDex позволил сократить размер хранящегося в памяти устройства кода приложения на 11,6%. Это касается и постоянной памяти, и оперативной, но не касается самих приложений, распространяющихся через маркеты.
Также в Android P был усовершенствован JIT-компилятор, а точнее его часть, ответственная за оптимизацию расположения данных в оперативной памяти, когда наиболее часто используемые и нужные при загрузке приложения методы размещаются ближе к началу оперативной памяти процесса. Напомню, что начиная с седьмой версии Android использует гибридный JIT/AOT-компилятор, который сначала выполняет приложения, используя виртуальную машину, а лишь затем переводит приложение в машинные инструкции.
Как происходит обработка установленного APK в Android O и Android P |
Ну и наконец, облачные профили. Это более простая, но эффективная идея. Во время исполнения любого приложения Android строит профиль его исполнения. В будущем такой профиль позволяет среде исполнения «подстроиться» под приложение и запустить его быстрее.
Идея функции Cloud Profiles в том, чтобы собрать данные профайлинга с разных устройств, агрегировать их и прикрепить к приложению в Google Play в виде единого файла профайлинга. Когда пользователь скачает приложение, он также получит файл профайлинга, и система сможет использовать его для ускорения запуска приложения. В дальнейшем профиль будет пополнен и расширен самим устройством.
На собственных приложениях Google система облачного профайлинга дала выигрыш в скорости первичного запуска примерно в 20%.
В ходе тестирования системы авторы сделали интересные выводы: в среднем в данные профайлинга попали только 14% кода приложения, а это значит, что остальные 86%, скорее всего, вообще не используются. Но это не обязательно мертвый код, это могут быть функции, отключенные на разных версиях Android, или, например, код отладки, отключенный в релизной версии.
Очередная экономия батарейки
App Standby Buckets in Android P will help further improve battery life — статья об еще одном интересном новшестве Android P под названием App Standby Buckets.
Предыстория здесь такова: в Android 6 Google придумала новейшую систему массового отстрела приложений, жрущих аккумулятор. Состояла она из двух частей: Doze и App Standby. Во время простоя смартфона (примерно час) в силу вступал Doze, он отключал фоновую активность, запрещал доступ в интернет, снимал вейклоки (они нужны, чтобы удерживать смартфон в режиме бодрствования), откладывал алармы, если они были не особо срочными.
В то же время работала система App Standby. Она занималась практически той же работой, но в отношении отдельно взятых приложений: дескать, раз уж юзер тобой не пользуется, а ты висишь и что-то там качаешь из интернета — лети в бан.
Насколько эффективной была эта система, никто так и не выяснил, но в Android P Google таки умудрилась ее расширить. Теперь речь идет не просто о классификации «работает / не работает», а о целой системе приоритетов. Все приложения теперь разделяются на группы:
- активные: приложение используется сейчас;
- регулярные: приложения используются регулярно;
- частые: приложения используются часто, но не каждый день;
- редкие: приложения используются реже одного-нескольких дней.
В зависимости от частоты использования Android будет выделять приложениям различные ресурсы. Такая вот дискриминация.
Другое
Kotlin в браузере
Embedding Kotlin Playground — с виду простой блог-пост, рассказывающий, как встроить среду исполнения Koltin в собственную страницу, где бы она ни хостилась. Сам код находится здесь.
Отмечу также, что у Kotlin есть полноценная веб-среда разработки, с помощью которой можно не только учиться программировать, но и писать полезный код.
Скриптовый Kotlin внутри Kotlin, который в Java
Run Kotlin Scripts (kts) from regular Kotlin Programs. Факт номер 1: приложения Kotlin могут быть выполнены в режиме скриптинга (переименовываем файл в .kts и скармливаем его kotlinc
). Факт номер 2: Java поддерживает интеграцию со скриптовыми языками (JSR-223). Факт номер 3: по умолчанию Kotlin компилируется в JVM (Java) и наследует почти все ее свойства.
Ну а суть статьи в том, как все это заставить работать вместе и сделать на Kotlin приложение, функциональность которого можно расширять с помощью скриптов на Kotlin. Выглядеть вызов скриптов Kotlin из Kotlin может так:
with(ScriptEngineManager().getEngineByExtension("kts")) {
eval("val x = 3")
val res2 = eval("x + 2")
assertEquals(5, res2)
}
Код доступен в репозитории KtsRunner.
Kotlin Cheat Sheet
Kotlin Cheat Sheet — простой понятный читшит о языке Kotlin, который можно повесить на стенку и начинать каждый день с созерцания красивых строк кода. Затрагивает: базовый синтаксис, управляющие структуры (включая фирменные «извращения» Kotlin), типы данных и конвертации, лямбды, разные типы функций, функции-расширения, идиоматические выражения. В целом почти полный курс по языку на семи страницах.
Kotlin Cheat Sheet — и еще один Kotlin Cheat Sheet, более сжатый, сконцентрированный на примерах и быстрых решениях.
Развлекуха с Anko
Anko Commons Tutorial — у разработчиков Kotlin есть один мало используемый, очень недооцененный проект. Он носит имя Anko и включает в себя множество подсобных утилит и функций, а в том числе превосходный DSL (язык в языке), позволяющий с комфортом описывать интерфейс без XML и ломания мозга (автор статьи с его помощью написал вполне успешное приложение).
Эта часть статьи посвящена только части Anko Commons, своего рода сборнику быстрых инструментов для Android-разработчиков. Ну и сразу несколько примеров.
Как запустить активность со сложным интентом? Так?
val intent = Intent(this, AnimeDetailActivity::class.java)
intent.putExtra("TITLE_KEY", anime.name)
intent.putExtra("DESCRIPTION_KEY", anime.description)
intent.putExtra("IMDB_LINK_KEY", anime.imdbLink)
intent.putExtra("IMAGE_KEY", anime.imageDrawable)
startActivity(intent)
Слишком увесисто, нам нужен Anko:
private fun openDetailActivity(anime: Anime) {
startActivity<AnimeDetailActivity>(
"TITLE_KEY" to anime.name,
"DESCRIPTION_KEY" to anime.description,
"IMDB_LINK_KEY" to anime.imdbLink,
"IMAGE_KEY" to anime.imageDrawable
)
}
Да какое там, если весь интент состоит из имени класса, то можно вообще сделать так:
startActivity<AboutActivity>()
А как насчет позвонить?
makeCall(002)
Отправить СМС:
sendSMS(номер, текст)
Ну и наши любимые сообщения:
toast("Я сообщение")
Диалоговое окно?
alert("message", "title").show()
Конечно же, его можно расширить, добавить кнопок и прочее.
То же самое с селекторами, прогресс-барами и много чем еще. Вообще, статья отлично иллюстрирует, как ужать код среднестатистического приложения раза этак в три.
Библиотеки
- androidexample365.com — огромное количество примеров реализации тех или иных функций в Android;
- restring — простая в использовании библиотека, позволяющая хранить строки приложения на удаленном сервере и автоматически загружать их в приложение;
- palumu — библиотека, позволяющая сделать элементы интерфейса плавающими;
- PersistantRecyclerAdapter — RecyclerView Adapter, способный сохранять данные между пересозданиями фрагментов и активностей;
- Cicerone — очередная попытка создать роутер, способный упростить логическую навигацию между компонентами приложения (основана не на фреймворках);
- Flashbar — очень развитая библиотека для вывода на экран самых разных типов сообщений, начиная от банальных Toast и Snackbar и заканчивая всевозможными окошками со всех сторон экрана;
- TlsLibrary — Kotlin DSL (язык в языке) для описания TLS-подключений;
- nanoscope — утилита трассировки с очень низким оверхедом (~20 наносекунд на один метод на Nexus 6);
- icondialoglib — диалог, позволяющий выбрать иконки, их цвет и другие параметры;
- domic — реактивная система работы с DOM Android;
- android-ruler-picker — рулетка для выбора нужных значений;
- UCE-Handler — библиотека, перехватывающая управление в момент падения приложения и выводящая информационное окно с возможностью просмотреть или отправить лог ошибки.
Инструменты
- dereflector — скрипт Frida для дерефлексии Java-кода (превращения непрямых вызовов методов в прямые);
- Fantastic Malware and Where to Find Them — большой каталог списков всевозможной малвари (в закладки!).