@Composable: шта је то, анотација Compose и област примене

Аутор: IT Sectr Објављено: 2026-06-27 Време читања: 8 мин

Анотација @Composable — основни елемент Jetpack Compose који претвара обичну Kotlin функцију у декларативни блок за изградњу корисничког интерфејса. Без ове анотације није могуће креирати ниједан екран у савременом Android развоју. Према Google Android Developers, 2026, преко 80% нових пројеката у Kotlin-у користи Compose за изградњу UI, а @Composable је најчешће коришћена анотација у екосистему.

Главно

  • @Composable — Kotlin анотација која омогућава функцији да опише UI декларативно
  • Composable функције могу позивати само друге Composable функције, поштујући контекст композиције
  • Поновно покретање Composable функција се дешава при промени улазних параметара или стања
  • Редослед позивања Composable функција није зајамчен — Compose оптимизује преизградњу UI
  • Именовање Composable функција прати PascalCase правило, као и сви компоненти у Compose

Шта је @Composable у Jetpack Compose

@Composable — је анотација језика Kotlin која означава функцију као намењену за описивање корисничког интерфејса у оквиру Jetpack Compose. Када Kotlin компилер наиђе ову анотацију, генерише додатан код који омогућава функцији да ради у контексту композиције — систему за управљање UI дрветом.

Анотација @Composable је представљена од стране Google-а 2021. године заједно са првом стабилном верзијом Jetpack Compose 1.0. Пре њеног појављивања, развој интерфејса за Android се одвијао искључиво кроз XML ознаке и View систем. @Composable је коренито променила приступ: уместо описивања UI-а у засебном фајлу за ознаке, програмер пише интерфејс директно у Kotlin-у.

Главна разлика између @Composable и обичних Kotlin функција — способност да чита и реагује на промене стања. Када промењива коју Composable функција чита промени вредност, систем аутоматски планира поновно покретање (рекомпозицију) те функције. Ово ослобађа програмера од ручног ажурирања UI кроз findViewById и setText.

Унутрашња механика @Composable се ослања на концепт слота — посебне меморијске области која се додељује свакој функцији у саставу композиције. У овом слоту чувају се вредности прослеђене функцији, као и помоћне информације потребне за поређење при каснијим позивима.

Како декларисати Composable функцију

За декларисање Composable функције довољно је додати анотацију @Composable пре кључне речи fun. Функција мора да се налази у пакету који увози анотацију из androidx.compose.runtime. Назив функције се препоручује да се пише великим почетним словом — ово је општеприхваћена конвенција у Compose заједници која визуелно одваја UI компоненте од обичних функција.

kotlin
import androidx.compose.runtime.Composable

@Composable
fun Greeting(name: String) {
    var count by remember { mutableStateOf(0) }
    Column {
        Text("Здраво, $name!")
        Button(onClick = { count++ }) {
            Text("Кликнуто $count пута")
        }
    }
}

Параметри Composable функције могу бити било какви — примитивни типови, низке, ламбде и чак друге Composable функције које се преносе кроз Slot API. Препоручује се да параметри буду непромењиви (val) да би се избегли нуспоредни ефекти при рекомпозицији. Сви промењиви подаци треба да се управљају кроз Compose механизме стања.

Composable функције не могу враћати произвољну вредност као обичне функције — њихов једини задатак је да изграде или ажурирају део UI дрвета. Ипак, постоје посебни обрасци као што је State Hoisting, у коме Compose функција прима стање и callback-е кроз параметре, остајући чиста и поновно употребљива.

Правила Composable функција у Kotlin-у

Compose систем намеће неколико строгих ограничења на то како Composable функције треба да изгледају и понашају се. Прво правило: Composable функција може позивати само друге Composable функције или обичне функције без нуспоредних ефеката. Ово осигурава предвидљивост композиције и исправан рад Compose оптимизација.

Друго правило се односи на редослед извршавања. Compose има право да позива Composable функције у било којем редоследу, па код у телу такве функције не треба да зависи од редоследа позивања суседних функција. Свака Composable функција треба да буде самодовољна на нивоу своје позиције у UI дрвету.

Треће правило — забрана нуспоредних ефеката у самом телу Composable функције. Операције као што су упис у базу података, слање мрежних захтева или промена спољашњих промењивих морају се извршавати само унутар посебних ефеката LaunchedEffect, DisposableEffect или SideEffect. Кршење овог правила доводи до непредвидљивог понашања при рекомпозицијама.

Четврто правило: Composable функције морају бити идемпотентне. Поновни позив са истим аргументима треба да произведе исти UI. Овај захтев је потребан за исправан рад skipping оптимизације, при којој Compose прескаче прецртавање функција чији се улазни подаци нису промењени.

kotlin
// Исправно: чиста Composable функција без нуспоредних ефеката
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
    Card(modifier = Modifier.clickable { onClick() }) {
        Text(text = user.name)
    }
}

// Неисправно: нуспоредни ефекат у телу
@Composable
fun WrongCard(userId: String) {
    // val result = viewModel.loadUser(userId)  // НИЈЕ ДОЗВОЉЕНО
    Text("Учитавање...")
}

Примери коришћења @Composable

Размотримо практичан пример креирања екрана профила коришћећем @Composable анотације. Овде демонстрирамо комбиновање више Composable функција, рад са стањем и модификаторима — кључним елементима сваког Compose распореда.

kotlin
@Composable
fun ProfileScreen(userId: String) {
    var isFollowed by remember { mutableStateOf(false) }

    Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
        ProfileHeader(userId = userId)
        Spacer(modifier = Modifier.height(16.dp))
        StatsRow(posts = 42, followers = 1280)
        Spacer(modifier = Modifier.height(24.dp))
        FollowButton(
            isFollowed = isFollowed,
            onToggle = { isFollowed = !isFollowed }
        )
    }
}

@Composable
fun ProfileHeader(userId: String) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        AsyncImage(model = "https://example.com/avatars/$userId",
            contentDescription = "User avatar")
        Spacer(modifier = Modifier.width(12.dp))
        Text(text = "Корисник #$userId", style = MaterialTheme.typography.headlineMedium)
    }
}

@Composable
fun StatsRow(posts: Int, followers: Int) {
    Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
        StatItem("Posts", posts)
        StatItem("Followers", followers)
    }
}

@Composable
fun StatItem(label: String, value: Int) {
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Text(text = "$value", style = MaterialTheme.typography.headlineSmall)
        Text(text = label, style = MaterialTheme.typography.bodySmall)
    }
}

У примеру, свака Composable функција је одговорна за свој део екрана: ProfileScreen управља општим стањем и композицијом потомака, ProfileHeader приказује аватар и име, а StatsRow — блок са статистиком. Овакав приступ прати принцип јединствене одговорности и поједностављује поновну употребу компонената.

Врсте Composable функција и њихова намена

У Jetpack Compose-у постоје три главне врсте Composable функција. Прва врста — контејнери (Row, Column, Box, LazyColumn) који одређују положај потомака. Друга — елементи приказа (Text, Image, Icon, Button) који рендерују одређене UI компоненте. Трећа — прилагођене Composable функције које комбинују уграђене компоненте у поновно употребљиве блокове.

Контејнери се разликују од обичних елемената по томе што прихватају content ламбду — последњи параметар типа @Composable () -> Unit. Управо овај механизам омогућава изградњу угнеждених UI дрвата: сваки појединачни контејнер ствара потомачку композицију са сопственим контекстом и меморијском облашчу.

Прилагођене Composable функције се деле на два подтипа: паметне (smart) и глупе (dumb). Паметне функције управљају стањем и логиком — садрже позиве remember, LaunchedEffect и других Compose API-ја. Глупе функције примају све податке кроз параметре и само их приказују. Подела на паметне и глупе компоненте побољшава тестирање и поновну употребу кода.

ВрстаПримерНамена
КонтејнерColumn, Row, BoxУправљање положајем потомака
ЕлементText, Image, ButtonПриказ садржаја и обрада уноса
ПрилагођениProfileCard, UserListКомбинација стандардних компонената

@Composable и поновно коришћење компонената

Главна предност @Composable анотације — могућност креирања поновно употребљивих UI компонената без наслеђивања и сложених хијерархија класа. За разлику од View система, где је сваки прилагођени елеменат захтевао креирање Java класе са конструкторима, Composable компонента је једноставно Kotlin функција са параметрима.

За обезбеђеђе поновне употребе примењује се образац Slot API, при коме Composable функција прихвата content ламбде за различите области свог распореда. На пример, Card компонента може да прима одвојен content за наслов, тело и доњи део, што га чини универзалним за било које екране апликације.

Модификатори (Modifier) играју кључну улогу у поновном коришћењу: омогућавају подешавање размака, величина, кликова и анимација без измене самог компонента. Препоручује се да увек преносите Modifier као параметар Composable функције са подразумеваном вредношчу: Modifier = Modifier — ово је стандардна пракса усвојена у званичним Google библиотекама.

kotlin
@Composable
fun SectionCard(
    modifier: Modifier = Modifier,
    title: String,
    content: @Composable () -> Unit
) {
    Card(modifier = modifier) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text(text = title, style = MaterialTheme.typography.titleMedium)
            Spacer(modifier = Modifier.height(8.dp))
            content()
        }
    }
}

Захваљујући Slot API-у, SectionCard компонента се може користити на различитим екранима са различитим садржајем — формуларима, списковима, текстуалним блоковима. Комбиновање модификатора и Slot API-а чини Compose компоненте максимално флексибилним без губитка типске сигурности коју обезбеђује Kotlin.

Често постављана питања

По чему се @Composable разликује од обичне Kotlin функције?

@Composable функција се извршава у контексту композиције и може да чита стање, аутоматски се поново покрећући при његовој промени. Обичне Kotlin функције немају приступ механизмима праћења стања и не учествују у изградњи UI дрвета.

Може ли се Composable функција позвати из обичне функције?

Не, Composable функције се могу позивати само из других Composable функција, јер је потребан посебан контекст композиције. За интеграцију Compose кода са обичним Kotlin-ом користи се метода setContent { } у Activity или ComposeView у View систему.

Зашто се Composable функције пишу великим почетним словом?

То је конвенција именовања усвојена у Compose заједници. Велико почетно слово визуелно одваја UI компоненте од обичних функција, пратећи правила именовања класа. Ово није захтев компилера, већ препоручена пракса у Google документацији.

Колико Composable функција може бити на једном екрану?

Нема ограничења у броју. У пракси, велики екран може да садржи 50–100 Composable функција, укључујући уграђене компоненте (Text, Button) и прилагођене. Compose оптимизује дрво функција и извршава само оне чији су се улазни подаци променили.

Може ли Composable функција да врати вредност?

Обично Composable функције враћају Unit, јер је њихов задатак да изграде UI. Ипак, постоје специјализоване функције као што су remember и derivedStateOf које су означене са @Composable и враћају вредности. То је изузетак, а не правило.

Закључак

  • @Composable — анотација за декларативно описивање UI у Jetpack Compose
  • Composable функције се позивају само унутар других Composable функција у посебном контексту
  • Идемпотентност — свако поновно извршавање са истим аргументима даје исти UI
  • Нуспоредни ефекти су забрањени у телу функције — само кроз LaunchedEffect и SideEffect
  • Slot API и Modifier омогућавају поновну употребу компонената без наслеђивања
  • Контејнерске функције (Row, Column, LazyColumn) прихватају content ламбде за угнеждене елементе
  • Препорука: преносите Modifier као параметар сваке прилагођене Composable функције са подразумеваном вредношчу

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође