Composable Function — је фундаментална јединица корисничког интерфејса у Jetpack Compose, која одређује како део екрана треба да изгледа и понаша се. Свака таква функција је означена анотацијом @Composable и извршава се у посебном контексту, омогућавајући Compose-у да прати зависности и аутоматски обнавља UI при промени података. Према Google Android Developers, 2026, правилно грађење Composable функција директно утиче на перформансе апликације и ефикасност рекомпозиције.
Главно
Composable Function — је функција у језику Kotlin означена анотацијом @Composable, која описује део корисничког интерфејса на декларативан начин. Уместо креирања и конфигурисања View објеката кроз Java код или XML ознаке, програмер једноставно пише како UI треба да изгледа при сваком стању података.
Основна разлика између Composable функције и традиционалног View система Android-а лежи у моделу ажурирања. У класичном приступу, програмер је ручно позивао findViewById, мењао текст кроз setText, управљао видљивошћу кроз setVisibility. Composable Function ослобађа од ове рутине: при промени података систем сам одређује које функције треба поново покренути и извршава само њих.
Kotlin компајлер, обрађујући анотацију @Composable, генерише додатни код који интегрише функцију у механизам композиције. Овај код укључује читање и писање у слотове — специјалне меморијске ћелије које чувају стање и параметре сваке Composable функције у тренутном UI стаблу. Захваљујући овој интеграцији, Compose зна које функције зависе од којих података.
Синтакса Composable функције је максимално концизна: довољно је додати @Composable испред кључне речи fun. Функција може прихватити било које параметре, укључивати друге Composable позиве у свом телу и користити Kotlin конструкције — услове, петље, when изразе — за условно приказивање UI.
@Composable
fun ProductItem(
product: Product,
modifier: Modifier = Modifier,
onAddToCart: () -> Unit
) {
Card(modifier = modifier.padding(8.dp)) {
Row(modifier = Modifier.fillMaxWidth().padding(12.dp),
verticalAlignment = Alignment.CenterVertically) {
Column(modifier = Modifier.weight(1f)) {
Text(text = product.name, style = MaterialTheme.typography.titleMedium)
Text(text = "${product.price}", color = MaterialTheme.colorScheme.primary)
}
Button(onClick = onAddToCart) {
Text("Додај у корпу")
}
}
}
}
У овом примеру, Composable функција ProductItem прима објекат Product, модификатор и колбек. Сва три параметра су имутабилна, што гарантује предвидљиво понашање при рекомпозицији. Модификатор је прослеђен као параметар са подразумеваном вредношћу — то је стандардна пракса која омогућава позивајућој страни да прилагоди размаке и величине.
Унутар Composable функције користе се уграђене компоненте Material Design-а (Text, Button, Card, TextField) или фундаментални примитиви (Canvas, Layout). Свака компонента прима параметре за конфигурисање изгледа и понашања, као и један или више модификатора кроз параметар modifier.
Модификатори (Modifier) — су ланац функција које мењају величину, положај, обраду догађаја и изглед компоненте. Редослед модификатора у ланцу је битан: clickable.semantics ради другачије од semantics.clickable, а padding.background боји позадину области укључујући padding, што је критично при дизајнирању.
Унутар Composable функције могу се користити услови if и when за условно приказивање делова UI, као и петље for за динамичке листе. Све ове конструкције раде природно, јер је Kotlin пуноправни програмски језик. Међутим, важно је запамтити: ако услов или петља садрже позиве Composable функција, оне такође учествују у рекомпозицији.
@Composable
fun ProductList(
products: List<Product>,
modifier: Modifier = Modifier
) {
LazyColumn(modifier = modifier) {
items(products, key = { it.id }) { product ->
ProductItem(
product = product,
onAddToCart = { /* add to cart */ }
)
}
}
}
Размотримо пример екрана за претрагу производа коришћењем неколико Composable функција. Овде су приказани типични обрасци: поље за унос са стањем, филтрирање листе, обрада празног резултата и учитавања.
data class Product(
val id: String,
val name: String,
val price: Double,
val category: String
)
@Composable
fun SearchScreen() {
var query by remember { mutableStateOf("") }
val products = remember(query) { getFilteredProducts(query) }
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
OutlinedTextField(
value = query,
onValueChange = { query = it },
label = { Text("Претражи производе") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
when (products) {
is Loading -> CircularProgressIndicator()
is Empty -> Text("Нема резултата")
is Result -> LazyColumn {
items(products.items, key = { it.id }) { product ->
ProductItem(product = product, onAddToCart = {})
}
}
}
}
}
Овај пример демонстрира неколико идиома истовремено: remember за чување стања упит за претрагу, remember(query) за филтрирање са кључем, when за три стања UI и LazyColumn за ефикасно приказивање листе. Сваки од ових идиома резултат је практичног искуства у развоју Compose апликација.
Composable функције примају параметре исто као и обичне Kotlin функције, али са једном важном разликом: параметар може бити друга Composable функција прослеђена кроз ламбду са анотацијом @Composable. Овај механизам се назива Slot API и представља главни образац за креирање контејнера за вишекратну употребу.
Slot API решава проблем који је у традиционалном View систему решаван кроз ViewGroup и програмско додавање дечјих View-ова. Уместо метода addView, Compose користи content ламбде — последњи параметар са типом @Composable () -> Unit. Позивајућа страна прослеђује овој ламбди било који UI, а сам контејнер само одређује његов положај.
Параметри Composable функције могу имати подразумеване вредности, што поједностављује њихово коришћење у различитим контекстима. Препоручује се да обавезним учините само оне параметре без којих функција не може да изврши свој задатак, а остале опремите разумним подразумеваним вредностима.
| Параметар | Тип | Пример |
|---|---|---|
| Обавезан | Било који тип | name: String |
| Опциони | Са подразумеваном вредношћу | modifier: Modifier = Modifier |
| Content | @Composable () -> Unit | content: @Composable () -> Unit |
| Колбек | Ламбда без @Composable | onClick: () -> Unit |
У Compose заједници се усталило неколико идиома који чине Composable функције читљивијим и предвидљивијим. Први — State Hoisting: стање се подиже на виши ниво, а Composable функција га добија кроз параметре. То чини функцију чистом и употребљивом у различитим контекстима.
Други идиом — Event-driven параметри. Уместо прослеђивања ViewModel-а или useCase-а у Composable функцију, прослеђују се само конкретни колбеци: onSave, onDelete, onNavigateToDetail. Ово смањује повезаност и поједностављује тестирање — за тест ProductItem-а није потребан ViewModel, само ламбда-стаб.
Трећи идиом — CompositionLocal за прослеђивање заједничких података кроз стабло композиције. Тема, густина екрана, тренутна рута — све се ово прослеђује кроз CompositionLocal, избегавајући ланце параметара кроз десетине Composable функција. Међутим, не треба злоупотребљавати CompositionLocal: експлицитни параметри су увек пожељнији од имплицитних зависности.
// State Hoisting: стање подигнуто на родитељску функцију
@Composable
fun CounterDisplay(
count: Int,
onIncrement: () -> Unit
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = "Бројач: $count", style = MaterialTheme.typography.headlineLarge)
Button(onClick = onIncrement) {
Text("+1")
}
}
}
// Коришћење са State Hoisting
@Composable
fun CounterScreen() {
var count by remember { mutableStateOf(0) }
CounterDisplay(
count = count,
onIncrement = { count++ }
)
}
Често постављана питања
Да, return је дозвољен, али са опрезом. Compose оптимизује рекомпозицију на нивоу појединачних функција, а рани return може нарушити ову оптимизацију. Боље је користити условне операторе if или when унутар тела функције.
У Kotlin-у Unit је синглтон објекат, а не празан тип. Composable функције враћају Unit, што технички значи да враћају сам Unit објекат. Међутим, у пракси то није битно — повратна вредност се игнорише од стране система композиције.
Прослеђивање променљивих колекција је могуће, али је лоша пракса. Ако се колекција промени, Compose неће сазнати за то, јер референца на објекат остаје иста. Користите immutable листе или mutableStateListOf за праћење промена.
За дебагирање користите Android Studio са Layout Inspector-ом, који приказује тренутно стабло Composable функција, вредности параметара и разлоге рекомпозиције. Такође ради обичан Kotlin дебагер — тачке прекида унутар Composable функција се коректно активирају при свакој рекомпозицији.
Composable функција увек враћа Unit, зато се return type не наводи. Покушај враћања другог типа изазваће грешку компајлације, јер анотација @Composable није компатибилна са повратним типовима који нису Unit.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође