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 функције не би требало да извршавају споредне акције директно (мрежни захтеви, тајмери, претплате) — one се позивају при свакој рекомпозицији, што би довело до дуплирања захтева. За споредне ефекте 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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође