В данной статье рассматриваются императивный и декларативный подходы к разработке интерфейсов, анализируются преимущества и недостатки библиотеки Jetpack Compose.
Ключевые слова: интерфейс, декларативный подход, императивный подход, Compose, XML, мобильная разработка
За каждым приложением стоит отдельный фрейморк для создания пользовательского интерфейса. Эти фреймворки играют огромную роль в том, как создаются приложения, а также насколько они производительны. Каждый из них имеет свой подход к созданию интерфейсов, но их можно обобщить до 2 групп: декларативной и императивной.
Исторически сложилось, что иерархия элементов интерфейса Android была представлена в виде дерева виджетов. По мере изменения состояния приложения, иерархию пользовательского интерфейса необходимо обновлять для отображения актуальных данных. Наиболее распространенным способом обновления интерфейса является обход дерева с помощью функций, а изменение отображения происходит путем вызова методов этих узлов, то есть изменения внутреннего состояния виджета.
Манипулирование представлениями вручную увеличивает вероятность ошибок. Если фрагмент данных отображается в нескольких местах, легко забыть обновить одно из отображающих его представлений. Также легко создавать ошибочные состояния, когда два обновления конфликтуют неожиданным образом. Например, обновление может попытаться установить значение узла, который только что был удален из пользовательского интерфейса. В целом сложность обслуживания программного обеспечения возрастает с увеличением числа представлений, требующих обновления.
Именно так происходит отображение и взаимодействие с интерфейсом со стороны разработчика сейчас. Существует множество библиотек, позволяющих немного облегчить работу разработчика, но они решают лишь часть проблем, а не все.
Декларативный подход в разработке является новой тенденцией, которая позволяет программистам продумывать пользовательский интерфейс на основе полученных данных. Этот шаблон фокусируется в первую очередь на том, что именно показывать.
Декларативный пользовательский интерфейс требует переосмысления разработки приложения, принятия того, что можно перестраивать части пользовательского интерфейса с нуля, а не изменять их. Современные процессоры достаточно быстры для этого и даже могут обрабатывать анимацию при перестройке всего экрана. В декларативной структуре изменения состояния данных запускают перестройку пользовательского интерфейса, которая удаляет целую категорию ошибок, связанных с состоянием, и упрощает рассуждения об обновлениях. Необходимо описать, как должен выглядеть пользовательский интерфейс для данного состояния, а платформа определяет, как это сделать, используя значения по умолчанию и контекст. Это значительно сокращает объем кода, который нужно написать, и облегчает его повторение.
Основным представителем декларативного подхода является Jetpack Compose, разрабатываемый компанией Google в рамках Jetpack — набора библиотек и инструментов для упрощения разработки под Android. Стоит рассмотреть ключевые причины перехода на данный фреймворк.
Библиотека совместима со всем существующим кодом, поэтому можно использовать ее в любых частях приложения. Можно интегрировать новый инструментарий пользовательского интерфейса в существующий проект.
Существующий инструментарий пользовательского интерфейса умеет в разы больше кода, по сравнению с новым. В Compose, в отличие от оригинального подхода, не нужно создавать файлы разметки. Меньший код помогает нам избежать множества ошибок. Это также делает код простым и легким в обслуживании.
При разработке с использованием фреймворка Compose используются два термина: «компоновка» (“composition”) и «перекомпоновка» (“recomposition”). Компоновка — это процесс, в котором выполняются составные функции и создается пользовательский интерфейс для пользователя. Перекомпоновка — это процесс обновления пользовательского интерфейса в результате изменения состояния или данных, которые составной объект использует для своего отображения. Во время перекомпоновки Compose может понять, какие данные использует каждая композиция, и обновляет только те компоненты пользовательского интерфейса, которые были изменены. Остальные составные элементы будут пропущены.
Все элементы представлены в виде составных функций в связи с чем их можно использовать сколько угодно раз. Составные функции могут выполняться в любом порядке и параллельно. Перекомпоновка пропускает как можно больше составных функций, насколько это возможно. Составная функция может выполняться выполнятся в каждом кадре анимации.
Поток данных в Compose устроен таким образом, что событие перемещается вверх по направлению к родительскому элементу, а данные передаются вниз от родительского элемента к его дочернему виджету. Важно то, что родитель всегда контролирует данные, передаваемые потомку.
Если данные должны быть разделены между несколькими виджетами, данные должны быть подняты до общего предка и переданы каждому из виджетов, которым это необходимо. Дочерние виджеты не должны считываться из глобальных переменных или глобальных хранилищ данных.
События, происходящие с уровня интерфейса, такие как нажатия кнопок, передаются обработчику событий, например, модели представления. Модель представления предоставит пользовательскому интерфейсу состояние через LiveData/Flow. По мере изменения состояния обновления передаются в составные файлы, которые затем проводят перекомпоновку с использованием последнего состояния.
Стоит отметить основные преимущества и недостатки. Первым преимуществом является низкий барьер входа. В первую очередь это вызвано тем, что разработка происходит на том же языке, на котором происходит разработка логики приложения. Команда Jetpack Compose также следует лучшим практикам разработки, уменьшая шаблонный код, при этом создавая качественную документацию, расположенную на официальном сайте документации Android.
Совместимость — одно из важнейших преимуществ, которое позволяет не переписывать проект, а использовать там, где это нужно. API работает в обоих направлениях — составные функции могут использоваться внутри XML, а сами функции могут содержать XML элементы.
Разработка Jetpack началась достаточно давно. Но несмотря на это, обновления набора библиотек и инструментов происходит достаточно регулярно, API эволюционирует и становится более зрелым. Но самым важным является тот факт, что в июле 2021 года была выпущена стабильная версия Jetpack Compose — 1.0.
Важно заметить, что Jetpack Compose может использоваться не только для разработки Android интерфейсов. Compose Multiplatform получил стабильную версию 1.0 в декабре 2021 года. Он позволяет производить разработку для Android, Windows, Linux, а также информационных систем в сети Интернет.
При разработке под Android используется один язык — Kotlin. Отсутствие XML и императивного программирования означает низкую связь и высокую согласованность, что приводит к меньшему количеству возможных проблем. Одним небольшим плюсом также является меньшее время сборки и размер приложения.
Теперь стоит отметить основные недостатки Compose. В первую очередь это то, что данный фреймворк все еще не является отраслевым стандартом. Все больше разработчиков обращают внимание на данную библиотеку, выражая свое одобрение, некоторые готовы заняться этим в будущем, говорят о его высоком потенциале. Но подавляющее большинство существующих систем используют стандартные инструменты Android и перестроить их моментально невозможно.
Следующей проблемой являются побочные эффекты совместимости. При использовании Compose совместно с XML разметкой увеличимается размер приложения и время сборки. Но как только приложение будет полностью перенесено на Compose, данные параметры будут лучше, чем до переноса.
Проблемы предварительного просмотра — перестраивайте каждый раз
Предварительный просмотр — это здорово. Это примерно в 10 раз лучше, чем XML, поскольку он предоставляет возможность просматривать (даже интерактивные) предварительные просмотры с поддельными данными. Но ничто не бывает бесплатным. Недостатком этого решения является повторный предварительный просмотр при каждом изменении кода, а сборки выполняются не так быстро.
По той причине, что Compose все еще находится в разработке, некоторые компоненты не поддерживаются, а некоторые функции не стабильны.
Новый способ описания пользовательского интерфейса означает изучение нового синтаксиса тестирования. Достаточно справедливо, но все же это дополнительные затраты на исследования и обучение.
Важным замечанием является и то, что необходимо продолжать читать о новых инструментах, библиотеках и архитектурах. Кроме того, придется менять версии по мере обновления системы, что приведет к постоянному рефакторингу кода. После выпуска версии 1.0 обновления стали менее частыми и радикальными с точки зрения изменений, но это не отменяет факта обновления системы при каждом обновлении библиотеки. Но постоянная работа над фреймворком означает множество улучшений, которые вселяют оптимизм в отношении Jetpack Compose.
Исходя из всего вышесказанного, можно сделать вывод, что Compose предоставляет современный, новый подход к определению пользовательского интерфейса. Поскольку составные функции очень похожи на обычные функции Kotlin, инструменты, с помощью которых вы пишете и производите рефакторинг их, будут аккуратно вписываться в ваш набор навыков разработки Android. Compose — это мощный скачок относительно создания UI, это изменение, которое значительно упростит многие проблемы, возникающие в устаревшей нагроможденной системе.
Литература:
- Императивное и декларативное программирование. — Текст: электронный // OTUS JOURNAL: [сайт]. — URL: https://otus.ru/journal/imperativnoe-i-deklarativnoe-programmirovanie/ (дата обращения: 23.01.2022).
- Обзор Android Jetpack Compose. — Текст: электронный // Русские Блоги: [сайт]. — URL: https://russianblogs.com/article/75801402833/ (дата обращения: 23.01.2022).
- Концепции Jetpack Compose, которые должен знать каждый разработчик. — Текст: электронный // AppTractor: [сайт]. — URL: https://apptractor.ru/info/articles/kontseptsii-jetpack-compose-kotorye-dolzhen-znat-kazhdyy-razrabotchik.html (дата обращения: 23.01.2022).
- Jetpack Compose. — Текст: электронный // Хабр: [сайт]. — URL: https://habr.com/ru/post/451112/ (дата обращения: 23.01.2022).