Начнём издалека. Мобильная операционная система Android (далее ОС Android) показала миру себя в далёком 2007 году (первая версия для пользователей вышла в 2008 году) и сразу завоевала сердца разработчиков по всему земному шару. Успех Android заключался в простоте и быстроте написания мобильных приложений. Вам всего лишь нужно было сделать интерфейс на языке разметки XML и связать его с логическим представлением экрана приложения (в роли которого тогда выступала только activity1, а о фрагментах тогда еще никто не знал), написанного на языке программирования Java.
Но всё хорошо было до поры до времени, пока экраны смартфонов оставались маленькими, а приложения простыми. Время шло, появлялись новые устройства на Android (планшеты, часы, телевизоры и автомобили), приложения обрастали новыми функциями и превращались в мобильных монстров у вас в кармане, да и сама ОС Android не отставала и стала в разы сложнее, как для пользователей, так и для разработчиков мобильных приложений.
Мобильные приложения стало сложнее писать и дольше по времени. Система построения интерфейса на базе XML-разметки (Android View System) изжила себя, так как для написания сложных приложений с большим количеством экранов программистам приходилось писать очень много шаблонного кода2 (boilerplate-код). Сложность самих экранов также увеличивалась, появлялась огромная вложенность компонентов пользовательского интерфейса друг в друга, из-за чего приложения стали дольше запускаться и пользователи получали негативный опыт использования таких мобильных приложений, что напрямую сказалось на оценках этих программ в магазине приложений Google Play, а также на доверии к разработчикам и самой операционной системе Android.
Компании Google нужно было что-то с этим сделать и она сделала. Первым шагом было предоставление нового вида контейнера для компонентов пользовательского интерфейса – ConstraintLayout, что позволило избежать глубокой вложенности элементов друг в друга и решило часть проблем, присущих view-системе. Дальнейшим шагом к улучшению разработки пользовательского интерфейса (user interface, далее UI) стала смена подхода, который применялся десятилетиями при написании программ. В большинстве систем (и не только в Android) при разработке использовался так называемый императивный подход (приказной подход), в основе которого лежит написание некого алгоритма, последовательно описывающего, как будет выглядеть UI приложения. Таким образом, программист последовательно задавал свойства отображаемым компонентам (расположение, цвет, размер шрифта и т. п.), мог сохранять значения этих свойств в переменные и повторно использовать в других частях программы. Использование этого подхода приводило к неприятным последствиям, которые проявлялись в виде появления побочных эффектов, когда состояние приложения или отдельного компонента UI могло поменяться в любой момент времени из любого места приложения. Это, естественно, приводило к ошибкам в приложении, исправление которых иногда могло занимать не один час отладки, чтобы хотя бы понять в чём была проблема. Поэтому в 2019 году на конференции разработчиков Google I/O компания объявила, что работает над новой системой построения пользовательского интерфейса Jetpack Compose, которая использует декларативный подход (описательный подход) при разработке UI. Используя этот подход, вы описываете простыми словами, как хотите, чтобы выглядел UI, а фреймворк3 Jetpack Compose сам за вас решит, на каких компонентах реализовать данный описанный интерфейс и какие конкретные значения задать свойствам компонентов этого UI.
Первая версия этого фреймворка, готового к использованию на бою в реальных мобильных приложениях, была представлена в июле 2021 года. Появлению этого фреймворка мы обязаны языку программирования Kotlin, который уже несколько лет является основным официальным языком программирования при разработке мобильных приложений для Android. Если говорить конкретнее, то Jetpack Compose использует функциональные возможности языка Kotlin, такие как функции высшего порядка. Это функции, которые на вход в качестве аргументов могут принимать другие функции, или возвращать какую-то функцию в качестве результата. По сути разработка интерфейса на фреймворке Jetpack Compose состоит в написании таких функций на языке Kotlin, использующих друг друга для создания иерархии пользовательского интерфейса. Более детально о том, на каких ключевых принципах построен фреймворк Jetpack Compose и как написать современное мобильное приложение для Android, используя этот фреймворк, мы поговорим в следующих главах.
- Activity (с английского, «активность» или «действие», но при общении используется транслитерация понятия – «активити») – базовый блок Android-приложения, представляющий собой активность (действие) пользователя в приложении, в простейшем случае выглядящий, как отдельное окно с элементами пользовательского интерфейса, который видит пользователь на экране смартфона. ↩︎
- Шаблонный код (boilerplate-код) – код, который вынужден писать разработчик, чтобы соблюдать требования языка программирования, операционной системы или, например, системы построения интерфейса на основе представлений (Android View System). ↩︎
- Фреймворк (framework, с английского, «каркас») – программная платформа, определяющая структуру вашей программы, то есть каркас, вокруг которого вы выстраиваете ваши собственные компоненты программы, следуя правилам построения архитектуры, заданных конкретным фреймворком, в данном случае Jetpack Compose. ↩︎