Урок 2: ПОЧЕМУ ОН (Jetpack Compose), а не XML

Урок 2: ПОЧЕМУ ОН (Jetpack Compose), а не XML

Введение

Давайте пройдемся по теории. В чем идея, задумка, зачем Jetpack Compose вообще появился и почему все так хотят сейчас писать на нем.

Я расскажу очень поверхностно про историю разработки на XML, попутно обращая внимания на нововведения и неудобства этого подхода. А в конце мы подведем итоги, сравнив все с Compose, чтобы была наглядна видна эволюция развития подхода к разработке. Чтобы для вас стали очевидны все преимущества декларативного фреймворка. Тогда вы полюбите его еще больше.

Как создавали интерфейс раньше?

Раньше для создания пользовательского интерфейса мы использовали XML-файлы, в которых описывали большую часть компонентов — кнопки, текстовые поля, контейнеры и так далее. Верстка интерфейсов была на языке разметки XML в виде вложенной структуры данных. В целом это было удобно для представления UI, который в своей сути тоже имеет вложенную структуру.

Базовые классы

Проектирование интерфейса на XML было похоже на создание дерева. Android сам парсил XML-файлы и создавал иерархию объектов View в памяти, которое отражало структуру интерфейса.

Разработчики Android представляли каждый элемент в виде класса. Классы были созданы для базовых компонентов, таких как View или ViewGroup (и их потомков), и выстроили их в иерархию. Например, каждый элемент экрана — кнопка, текстовое поле или изображение – наследуется от базового класса View, а контейнеры от ViewGroup.

Также разработчики могли визуально рисовать интерфейсы, а затем видеть их в визуальном редакторе. То есть, ты пишешь код, и сразу на превью видишь, как интерфейс выглядит. Такой подход называется WYSIWYG — what you see is what you get. Качество таких превью, безусловно, оставляет желать лучшего. Но это лучше, чем ничего.

Надо сказать, что базовые классы и их наследники огромны. Они перегружены логикой и имеют сложную иерархию. Их довольно тяжело поддерживать и расширять, особенно при создании кастомных компонентов. Это усложняет процесс разработки и приводит к увеличению часов на разработку приложения.

Перерисовка компонентов

Естественно система должна всю это иерархию как-то отображать на экране. Перерисовка интерфейса могла существенно влиять на производительность.

Отрисовка осуществляется самой платформой. Мы только строим это дерево и можем взаимодействовать с ним, вызывая функции классов для изменения каких-либо состояний.

При изменении параметров приходится перегруппировывать элементы, выполнять новый расчет размеров и делать множественные вызовы метода measure.

Эффективность здесь зависит от того, насколько качественно был реализован процесс верстки, глубина вложенности контейнеров и тому подобное. И поскольку мы работаем с XML, неизбежна стадия инфлейтинга.

Управление состоянием

Окей, и с этим научились жить. Количество кода росло, логика усложнялась. В первые годы разработчики применяли императивный подход к изменению интерфейса. Изменения UI происходили напрямую в разных частях кода. А заниматься хранением состояния и централизованно им управлять начали значительно позже появления самой платформы.

Понятие состояния как единого «источника правды» (source of truth) начало набирать популярность с появлением архитектурных паттернов, таких как MVP и позже MVVM.

То есть в какой-то момент разработчики начали понимать преимущества подхода, где используется стейт (состояние), который отрисовывается в UI. Мы просто меняем состояние, а UI автоматически обновляется – вспоминаем проходимый ранее механизм подписки через Observer.

Например, у нас есть UI-стейт во ViewModel в виде LiveData или в последнее время чаще StateFlow, мы берем, подписываемся и полностью отображаем его в интерфейсе. Это удобно: мы просто присваиваем значения элементам UI, не смешивая логику и отрисовку.

Реактивное программирование

Возвращаясь к Compose, важно упомянуть, что этот декларативный фреймворк сочетает в себе помимо лаконичного языка, еще и модель реактивного программирования. Вся архитектура Compose построена на принципах реактивности. Реактивное программирование — это подход, при котором система автоматически реагирует на изменения данных, вместо того чтобы вручную проверять их состояние.

В Compose этот принцип реализуется через декларативный подход: ты описываешь, как должен выглядеть UI в зависимости от состояния данных, а сама система берет на себя заботу о том, чтобы обновить интерфейс при изменении этих данных. Нет необходимости вручную подписываться на изменения с помощью LiveData или StateFlow — всё работает автоматически. Когда данные изменяются, компоненты интерфейса перерисовываются только тогда, когда это необходимо, а не при каждом изменении состояния, как это было в старом императивном подходе.

Это и есть суть реактивного программирования, которая лежит в основе Jetpack Compose. Это новый виток эволюции в Android по части работы с состоянием.

Проблемы с превью и временем разработки

Стейты сильно упростили всем разработчикам жизнь. Но всё равно верстать в XML все еще остается довольно неудобно.

  • Превью часто не соответствует тому, что ты рисуешь. То есть то, что ты видишь, не всегда будет выглядеть так же на устройстве.
  • В превью используются только mock-данные. Чтобы увидеть, как экран будет выглядеть с реальными данными, приходится собирать приложение и запускать его на устройстве.
  • Если нужно проверить какой-то экран, который находится глубоко в навигации, приходится ещё переходить между несколькими экранами. Или делать специальные debug-экраны, с которых осуществляется быстрый переход на разрабатываемый экран.

На первый взгляд это может показаться незначительным, но такие мелочи сильно замедляют разработку. Поэтому у разработчиков часто возникает недоверие к превью. Даже если оно отображает экран с вероятностью 90% правильно, всё равно приходится компилировать и проверять вручную. Иначе нельзя. А это занимает время. А время, как известно, — самый ценный ресурс программиста.

Как Jetpack Compose решает

Подбираемся ко второй части материала. Тезисно вспомним, какие особенности или даже неудобства мы испытывали при работе с XML:

  • Ну первое и очевидное это то, что необходимо знать дополнительный язык разметки. Compose естественно устраняет необходимость использовать XML для описания интерфейсов. Все пишется на Kotlin.
  • При работе с компонентами мы никак не связаны с громоздкими View-классами и сложными иерархиями. Каждый элемент интерфейса представлен как функция, которая описывает его внешний вид и поведение.
  • Compose изменяет интерфейс только тогда, когда изменяется состояние. Более того, перерисовывается только тот элемент на экране, который изменил свое состояние.
  • Кроме того, здесь нет этапа инфлейтинга, то есть все создается напрямую через методы. Это сокращает количество операций, связанных с преобразованием данных и существенно улучшает время отклика приложения, особенно при сложном UI.
  • Теперь что касается состояния, реактивщины и всего такого. В традиционном подходе мы создаем, например, LiveData. Затем создаем наблюдатель во фрагменте через него подписываемся на изменения этой переменной с “живыми данными”. Соответственно при обновлении LD или StateFlow внутри ViewModel – срабатывал наблюдатель и мы в нем перерисовывали UI. В Compose этот процесс значительно упрощается, становится более компактным. Вместо LiveData мы используем реактивные состояния. Главное отличие в том, что не нужно явно устанавливать Observer, подписываться и вручную прописывать методы обновления соответствующих View.

Что это такое и как это работает мы обязательно препарируем на уроках подробно.

  • В Compose превью работает не только с “моками”, но и позволяет подключать реальные данные из других источников. Это значит, что ты сразу видишь, как экран будет выглядеть в реальном приложении, без необходимости собирать APK и запускать его на устройстве. Более того, можно создавать несколько вариантов одного экрана с разными состояниями.
  • Также мы можем мгновенно видеть изменения в интерфейсе без полной компиляции приложения. Это кардинально ускоряет процесс работы: поправил отступ или добавил элемент — и сразу увидел результат. При работе с XML такого добиться нельзя.

Заключение

В целом, если быть кратким, тут только основные тезисы в пользу Compose, всю мощь и прелесть вы ощутите когда начнете разрабатывать на нем.

Бесплатные Telegram-боты для обучения

Практика с проверкой кода и помощью ИИ-ментора

AndroidSprint AI Mentor

Проверяет Pull Request'ы в GitHub, проводит тестовые собеседования с голосом и таймером, помогает разбираться с кодом 24/7

Попробовать ИИ-ментора →

KotlinSprint Bot

22 урока Kotlin, 220 тестов, 120 практических задач с код-ревью

Начать обучение Kotlin →

AndroidSprint Bot

Тесты по Android SDK, Jetpack Compose, архитектуре приложений

Тесты по Android →

Тебе также может быть интересно

Узнать подробнее
Курс AndroidSprint

Глубокое обучение Android разработке с 0 до получения оффера. Только персональная практика с гарантией получения продуктового опыта.

Курс AndroidSprint - Глубокое <strong>обучение Android разработке с 0 до получения оффера</strong>. Только персональная практика с гарантией получения продуктового опыта.
Узнать подробнее
Узнать подробнее
Практикум по Kotlin

Изучение Котлин с 0 для профессиональной разработки. Личный ментор и разбор кода задач через git-flow.

Практикум по Kotlin - Изучение Котлин <strong>с 0 для профессиональной разработки</strong>. Личный ментор и разбор кода задач через git-flow.
Узнать подробнее
Узнать подробнее
Бесплатные уроки по Kotlin разработке

Самостоятельное освоение базы по языку для дальнейшего развития в Android/back-end разработке или в автотестах.

Бесплатные уроки по Kotlin разработке - <span>Самостоятельное освоение базы по языку для дальнейшего развития в Android/back-end разработке или в автотестах.</span>
Узнать подробнее
Узнать подробнее
Onboarding в разработку

Полное обучение Android разработке с нуля до получения оффера. Делаем упор на практику и обратную связь

Onboarding в разработку - <span>Полное обучение Android разработке с нуля до получения оффера. Делаем упор на практику и обратную связь</span>
Узнать подробнее
Узнать подробнее
Обучающий Kotlin телеграм бот (с тестами)

Ваш основной инструмент для изучения основ языка. Бесплатные тесты и практика внутри.

Обучающий Kotlin телеграм бот (с тестами) - Ваш основной <span>инструмент для изучения основ языка.</span> Бесплатные тесты и практика внутри.
Узнать подробнее
Узнать подробнее
Бесплатные уроки по Android разработке

Самостоятельное обучение разработке Андроид приложений. Понятные видеоуроки с разжеванными примерами.

Бесплатные уроки  по Android разработке - Самостоятельное <span>обучение разработке Андроид приложений.</span> Понятные видеоуроки с разжеванными примерами.
Узнать подробнее
Узнать подробнее
Курс по UI/Unit тестированию

Для ручных тестировщиков, которые готовы осваивать автотесты с использованием актуального стека технологий. [в разработке]

Курс по UI/Unit тестированию - Для ручных тестировщиков, которые <span>готовы осваивать автотесты</span> с использованием актуального стека технологий. [в разработке]
Узнать подробнее
Узнать подробнее
Обучающий Android телеграм бот (с тестами)

Бесплатные теоретические тесты для самопроверки. А также информер на практических спринтах по Android.

Обучающий Android телеграм бот (с тестами) - Бесплатные <span>теоретические тесты для самопроверки.</span> А также информер на практических спринтах по Android.
Узнать подробнее