Jetpack Compose: що це, ключові поняття та composable функції

Автор: IT Sectr Опубліковано: 2026-05-01 Час читання: 9 хв

Jetpack Compose — це сучасний декларативний тулкіт для побудови інтерфейсів Android на Kotlin. Розробник описує UI через composable функції, а тулкіт автоматично перемальовує лише змінені частини. За даними Android Developers (2026), Jetpack Compose працює на Android 5.0 (API 21) і вище, підтримує Material Design 3 та досягає 120 FPS на пристроях середнього сегмента завдяки власній системі Recomposition — розумному diff-алгоритму, що оновлює лише змінені віджети.

Головне

  • Jetpack Compose — декларативний UI-фреймворк для Android, де інтерфейс будується через анотовані функції @Composable на Kotlin.
  • Recomposition — механізм автоматичного оновлення лише тих компонентів, чиї дані змінилися, що забезпечує 120 FPS.
  • State керується через mutableStateOf, collectAsState та StateFlow — при зміні значення композиція перезапускається для залежних в'юх.
  • Modifier — ланцюжок функцій для налаштування відступів, розмірів, фону, кліків та анімацій без успадкування класів.
  • Side Effects — LaunchedEffect, DisposableEffect та rememberCoroutineScope — керують побічними діями: таймери, мережеві запити, підписки.

Що таке Jetpack Compose?

Jetpack Compose — це декларативний фреймворк від Google для побудови користувацьких інтерфейсів Android, анонсований у 2019 році та досягнутий стабільного релізу в 2021-му. На відміну від старої View System (XML-розмітка + Activity/Fragment), Compose використовує анотовані Kotlin-функції — @Composable. Інтерфейс описується цілком на Kotlin: немає розділення на XML та код. Це усунуло клас помилок, пов'язаних з неспівпадінням id у XML та Kotlin (type-safe synthetic не рятував при рефакторингу).

Compose побудований на власній системі рендерингу — Canvas, не прив'язаній до View-ієрархії. Кожен Composable малює себе на Canvas напряму, оминаючи onMeasure/onDraw View System. Це дає приріст продуктивності на складних екранах: у тестах Google (2023) екран на Compose з 200 елементами відмальовувався на 40% швидше за аналогічний на RecyclerView + ViewHolder.

Мінімальні вимоги та сумісність

Для роботи Compose потрібен minSdk 21 (Android 5.0) та Kotlin 1.9+. Compose BOM (Bill of Materials) синхронізує версії всіх бібліотек Compose. Фреймворк сумісний з існуючим кодом на View System: Compose вбудовується через ComposeView у XML-розмітку, а старі View — через AndroidView у Compose-ієрархію. За даними Google Play Console (2025), Android 5.0+ покриває 97% активних пристроїв, тому сумісність не є обмеженням для більшості проєктів.

Composable функції та композиція

@Composable — це анотація, що перетворює звичайну Kotlin-функцію на будівельний блок UI. Composable функція описує, як має виглядати фрагмент інтерфейсу — текст, кнопка, список. Замість повернення значення функція емітує (emits) UI-компоненти в композицію. Це схоже на генератор: кожна функція додає елементи на екран при виклику.

kotlin
@Composable
fun ProfileCard(name: String, avatarUrl: String) {
    Card(
        modifier = Modifier.fillMaxWidth().padding(16.dp),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surface
        )
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            AsyncImage(
                model = avatarUrl,
                contentDescription = "Аватар",
                modifier = Modifier.size(48.dp).clip(CircleShape)
            )
            Spacer(Modifier.width(12.dp))
            Text(
                text = name,
                style = MaterialTheme.typography.titleMedium
            )
        }
    }
}

Функція ProfileCard приймає параметри (name, avatarUrl) та емітує Card → Row → AsyncImage + Text. Композиція — це дерево емітованих компонентів за один прохід. Якщо параметри не змінилися, Compose пропускає виклик функції (recomposition skip). Якщо змінився лише name, буде викликаний лише Text, решта елементів не буде перемальована. Такий intelligent recomposition — ключова перевага продуктивності Compose перед ручною оптимізацією View System.

Слоти та Content Lambda

Composable функції активно використовують слоти — trailing lambda, content: @Composable (() -> Unit). Це дозволяє створювати контейнери: Card, Column, Row приймають content-лямбду, і вміст вбудовується на місце слота. Slot API замінив XML-атрибути на кшталт android:layout_gravity — тепер розташування дочірніх елементів задається Kotlin-кодом всередині контент-блоку.

Керування станом у Compose

Стан у Compose — це будь-яке значення, яке може змінюватися з часом. Коли стан змінюється, Compose планує recomposition для всіх компонентів, що читають цей стан. Механізм нагадує React hooks: mutableStateOf повертає MutableState<T>, читання .value автоматично підписує поточну композицію на зміни.

kotlin
@Composable
fun CounterExample() {
    var count by remember { mutableStateOf(0) }

    Column(modifier = Modifier.padding(16.dp)) {
        Text("Натиснуто: $count")
        Button(onClick = { count++ }) {
            Text("Збільшити")
        }
    }
}

@Composable
fun UserScreen(viewModel: UserViewModel) {
    val userName by viewModel.userName.collectAsState()
    Text("Користувач: $userName")
}

remember зберігає значення між рекомпозиціями — інакше mutableStateOf створювався б заново при кожному оновленні UI. collectAsState() конвертує StateFlow з ViewModel у Compose-сумісний стан. Рекомендація — для екранного стану використовувати ViewModel з StateFlow, для локального (наприклад, розгорнута картка) — mutableStateOf. Це розділення відповідає принципу «розумні/тупі» компоненти.

State Hoisting

State Hoisting — паттерн винесення стану з дочірнього компонента в батьківський. Батько передає значення та callback через параметри, дочірній викликає callback при зміні. Батько зберігає mutableStateOf, дочірній — лише параметри. Це робить компонент перевикористовуваним і тестованим: той самий TextField можна використовувати з будь-яким джерелом даних.

Modifier — налаштування зовнішнього вигляду

Modifier — це об'єкт, що описує трансформації Composable: розмір, відступи, фон, обробку кліків, анімацію, скрол. Модифікатори застосовуються через ланцюжок викликів: Modifier.fillMaxWidth().padding(16.dp).background(Color.Blue).clickable { }. Кожен виклик повертає новий Modifier з доданою властивістю — жодної мутації оригінального об'єкта.

Порядок модифікаторів важливий. Modifier.padding(16.dp).background(Color.Blue) зафарбовує область з відступом. Modifier.background(Color.Blue).padding(16.dp) зафарбовує внутрішній прямокутник, а відступ залишається прозорим. Механіка схожа на CSS box model: padding спочатку → background працює як margin + background; background спочатку → padding — як background + внутрішній відступ. Розробнику достатньо запам'ятати: padding спочатку = зовнішній відступ, padding потім = внутрішній.

Кастомні модифікатори

Якщо вбудованих модифікаторів недостатньо, створюється кастомний через Modifier.composed { ... } або Modifier.then(). Всередині кастомного модифікатора можна використовувати layout-вимірювання (Modifier.layout { measurable, constraints -> ... }), малювання (Modifier.drawWithContent { ... }), жести (Modifier.pointerInput { ... }). Приклад: модифікатор для пульсуючої анімації при натисканні — вимірює розмір, при кліку запускає scale-анімацію через animateFloatAsState.

Для анімацій Compose надає animate*AsState (animateFloatAsState, animateColorAsState, animateDpAsState) — значення анімуються між старим і новим станом при зміні. Якщо потрібно анімувати появу/зникнення — AnimatedVisibility та AnimatedContent з вбудованими переходами (fade, slide, expand). Всі анімації працюють на graphics layer, не викликаючи зайву композицію.

Side Effects: LaunchedEffect, DisposableEffect, remember

Composable функції не повинні виконувати побічні дії безпосередньо (мережеві запити, таймери, підписки) — вони викликаються на кожній рекомпозиції, що призведе до дублювання запитів. Для побічних ефектів Compose надає сімейство Effect-функцій: LaunchedEffect запускає корутину при вході в композицію та скасовує при виході, DisposableEffect — для ресурсів, що потребують явного очищення (сенсори, BroadcastReceiver).

kotlin
@Composable
fun SensorReader() {
    val context = LocalContext.current
    var sensorValue by remember { mutableStateOf(0f) }

    DisposableEffect(Unit) {
        val sensor = registerSensorListener(context) { value ->
            sensorValue = value
        }
        onDispose {
            unregisterSensorListener(sensor)
        }
    }

    Text("Значення: $sensorValue")
}

@Composable
fun UserGreeting(userId: String) {
    LaunchedEffect(userId) {
        val profile = api.fetchProfile(userId)
        // оновлення стану
    }
}

LaunchedEffect(userId) перезапускається, якщо userId змінився — попередня корутина скасовується, нова запускається з новим userId. Це позбавляє від ручного керування скасуванням запитів. DisposableEffect(Unit) — ефект з фіксованим ключем Unit, спрацьовує при вході в композицію та викликає onDispose при виході. SensorReader реєструє слухача та відписується при виході з екрана — без ризику витоку.

rememberCoroutineScope

Якщо корутину потрібно запустити не при вході в композицію, а за подією (натискання кнопки), використовується rememberCoroutineScope(). Він повертає CoroutineScope, прив'язаний до життєвого циклу Composable, що не потребує DisposableEffect. Приклад: запуск мережевого запиту при кліку на кнопку — scope.launch { viewModel.loadData() }.

Jetpack Compose vs View System: порівняння

Вибір між Compose та View System — головне архітектурне питання Android-розробника в 2026 році. Обидві технології підтримуються Google, але Compose — основний напрям, на який Google витрачає ресурси. View System отримує лише критичні виправлення і не розвивається. Різниця проявляється в синтаксисі, керуванні станом, продуктивності та часі розробки.

АспектJetpack ComposeView System
Опис UIKotlin @Composable функціїXML-розмітка + Activity/Fragment
СтанmutableStateOf, StateFlow, автоматичне перемальовуванняfindViewById, вручну: setText, notifyDataSetChanged
ПродуктивністьIntelligent recomposition, Canvas-рендерингView-ієрархія, measure/layout/draw
Анімаціїanimate*AsState, AnimatedVisibility, вбудованіValueAnimator, ObjectAnimator, Transition
СумісністьminSdk 21, ComposeView/AndroidView мостиВсі версії, будь-яка
Розмір APK+3–5 МБ на ComposeБез накладних витрат

Для нових проєктів Google рекомендує Jetpack Compose як стандарт UI-розробки. View System залишається для підтримки коду, написаного до 2021 року, та випадків, коли потрібен мінімальний розмір APK (наприклад, для ринків, що розвиваються, з пристроями початкового рівня). Compose скорочує обсяг UI-коду на 30–50% порівняно з View System завдяки декларативному синтаксису та вбудованій анімації.

Часті запитання

Чи можна використовувати Compose в існуючому проєкті на View System?

Так, через ComposeView у XML-розмітці. Додайте dependency на Compose та оберніть екран або його частину в ComposeView { MyComposable() }. Міграція поекранна.

Чому мій Composable перемальовується занадто часто?

Причина — стан піднімається занадто високо або використовуються змінювані об'єкти. Виправлення: derivedStateOf для похідних даних та remember для стабільних посилань.

Як реалізувати список у Compose?

Використовуйте LazyColumn (аналог RecyclerView). Елементи створюються та перевикористовуються в міру скролу. Для складних списків з різними типами комірок — LazyColumn { items(items, key = { it.id }) { ... } }.

Чи потрібно вчити View System перед Compose?

Ні, можна починати одразу з Compose. Знання View System допомагає при підтримці легасі-коду, але Compose — самостійна екосистема зі своєю документацією та паттернами.

Чи підтримує Compose Material 3?

Так, Material 3 — стандартна тема Compose з 2023 року. Підключається через implementation("androidx.compose.material3:material3"). Material 2 вважається застарілим.

Підсумки

  • Jetpack Compose — декларативний UI-фреймворк для Android, де весь інтерфейс пишеться на Kotlin через @Composable функції.
  • Recomposition автоматично перемальовує лише змінені компоненти, забезпечуючи 120 FPS без ручної оптимізації.
  • Стан керується через mutableStateOf, collectAsState та StateFlow; паттерн State Hoisting робить компоненти перевикористовуваними.
  • Modifier — ланцюжок трансформацій для налаштування зовнішнього вигляду, анімацій та поведінки без успадкування класів.
  • Side Effects (LaunchedEffect, DisposableEffect) ізолюють побічні дії від рекомпозиції, запобігаючи витокам та дублюванню запитів.
  • LazyColumn замінює RecyclerView з меншою кількістю коду, а AnimatedVisibility — складні Animator-ланцюжки.
  • Google рекомендує Compose для всіх нових проєктів; View System залишається для підтримки легасі-коду та випадків, коли критичний мінімальний розмір APK.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також