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 — е декларативна рамка от 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 — е анотация, която превръща обикновена Kotlin функция в градивен блок на UI. Composable функцията описва как трябва да изглежда фрагмент от интерфейса — текст, бутон, списък. Вместо да връща стойност, функцията излъчва UI компоненти в композицията. Това прилича на генератор: всяка функция добавя елементи към екрана при извикване.
@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.
Composable функциите активно използват слотове — trailing lambda, content: @Composable (() -> Unit). Това позволява създаване на контейнери: Card, Column, Row приемат content ламбда и съдържанието се вгражда на мястото на слота. Slot API замени XML атрибути като android:layout_gravity — сега позицията на подчинените елементи се определя от Kotlin код вътре в content блока.
Състояние в Compose — е всяка стойност, която може да се променя във времето. Когато състоянието се промени, Compose планира recomposition за всички компоненти, които четат това състояние. Механизмът напомня на React hooks: mutableStateOf връща MutableState, четенето на .value автоматично абонира текущата композиция за промени.
@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 — модел за изнасяне на състояние от подчинен компонент в родителския. Родителят предава стойност и callback чрез параметри, подчиненият извиква callback при промяна. Родителят съхранява mutableStateOf, подчиненият — само параметрите. Това прави компонента многократно използваем и тестваем: същият TextField може да се използва с всеки източник на данни.
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 първо = външно разстояние, padding после = вътрешно.
Ако вградените модификатори не са достатъчни, се създава персонализиран чрез Modifier.composed { ... } или Modifier.then(). Вътре в персонализирания модификатор могат да се използват измервания на оформлението (Modifier.layout { measurable, constraints -> ... }), рисуване (Modifier.drawWithContent { ... }), жестове (Modifier.pointerInput { ... }). Пример: модификатор за пулсираща анимация при натискане — измерва размера, при кликване стартира анимация на мащабиране чрез animateFloatAsState.
За анимации Compose предоставя animate*AsState (animateFloatAsState, animateColorAsState, animateDpAsState) — стойностите се анимират между старо и ново състояние при промяна. Ако е необходима анимация за появяване/изчезване — AnimatedVisibility и AnimatedContent с вградени преходи (fade, slide, expand). Всички анимации работят на graphics layer, без да причиняват ненужна композиция.
Composable функциите не трябва да изпълняват странични действия директно (мрежови заявки, таймери, абонаменти) — те се извикват при всяка рекомпозиция, което би довело до дублиране на заявки. За странични ефекти Compose предоставя семейство функции Effect: LaunchedEffect стартира корутина при влизане в композицията и я отменя при излизане, DisposableEffect — за ресурси, изискващи изрично почистване (сензори, BroadcastReceiver).
@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(). Той връща CoroutineScope, обвързан с жизнения цикъл на Composable, без да изисква DisposableEffect. Пример: стартиране на мрежова заявка при кликване на бутон — scope.launch { viewModel.loadData() }.
Изборът между Compose и View System — основният архитектурен въпрос на Android разработчика през 2026 г. И двете технологии се поддържат от Google, но Compose е основната посока, в която Google инвестира ресурси. View System получава само критични корекции и не се развива. Разликата се проявява в синтаксиса, управлението на състоянието, производителността и времето за разработка.
| Аспект | Jetpack Compose | View System |
|---|---|---|
| Описание на UI | Kotlin @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 MB за Compose | Без допълнителни разходи |
За нови проекти Google препоръчва Jetpack Compose като стандарт за UI разработка. View System остава за поддръжка на код, написан преди 2021 г., и случаи, когато се изисква минимален размер на APK (напр. за развиващи се пазари с устройства от начално ниво). Compose намалява обема на UI кода с 30–50% в сравнение с View System благодарение на декларативния синтаксис и вградените анимации.
Често задавани въпроси
Да, чрез ComposeView в XML. Добавете dependency на Compose и обвийте екрана или част от него в ComposeView { MyComposable() }. Миграцията е екран по екран.
Причина — състоянието се повдига твърде високо или се използват променливи обекти. Поправка: derivedStateOf за производни данни и remember за стабилни референции.
Използвайте LazyColumn (аналог на RecyclerView). Елементите се създават и преизползват по време на скрол. За сложни списъци с различни типове клетки — LazyColumn { items(items, key = { it.id }) { ... } }.
Не, можете да започнете директно с Compose. Познаването на View System помага при поддръжка на наследен код, но Compose е самостоятелна екосистема със собствена документация и модели.
Да, Material 3 — е стандартната тема на Compose от 2023 г. Свързва се чрез implementation(“androidx.compose.material3:material3”). Material 2 се счита за остарял.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също