A @Composable annotáció — a Jetpack Compose alapvető eleme, amely egy szokványos Kotlin függvényt deklaratív felhasználói felület építőkövé alakít. E nélkül az annotáció nélkül egyetlen képernyő sem hozható létre a modern Android fejlesztésben. A Google Android Developers, 2026 szerint az új Kotlin projektek több mint 80%-a használja a Compose-t UI építésére, és a @Composable a leggyakrabban használt annotáció az ökoszisztémában.
Főbb pontok
@Composable — a Kotlin nyelv annotációja, amely megjelöl egy függvényt a felhasználói felület leírására a Jetpack Compose keretrendszerben. Amikor a Kotlin fordító találkozik ezzel az annotációval, további kódot generál, amely lehetővé teszi a függvény számára a kompozíció kontextusában — az UI fa kezelő rendszerében — való működést.
A @Composable annotációt a Google 2021-ben vezette be a Jetpack Compose 1.0 első stabil verziójával együtt. Megjelenése előtt az Android interfészeinek fejlesztése kizárólag XML jelöléssel és View rendszerrel történt. A @Composable gyökeresen megváltoztatta a megközelítést: ahelyett, hogy az UI-t külön jelölőfájlban írná le, a programozó közvetlenül Kotlinban írja az interfészt.
A fő különbség a @Composable és a szokványos Kotlin függvények között — az állapotváltozások olvasásának és az azokra való reagálásnak a képessége. Amikor egy változó, amelyet egy Composable függvény olvas, megváltoztatja az értékét, a rendszer automatikusan ütemezik a függvény újraindítását (rekompozíció). Ez megszabadítja a programozót az UI kézi frissítésétől a findViewById és setText segítségével.
A @Composable belső mechanikája a slot koncepcióján alapul — egy speciális memóriaterületen, amely minden függvény számára van fenntartva a kompozícióban. Ebben a slotban tárolódnak a függvénynek átadott értékek, valamint az összehasonlításhoz szükséges szervizinformációk a későbbi hívásokhoz.
Egy Composable függvény deklarálásához elegendő a @Composable annotációt hozzáadni a fun kulcsszó előtt. A függvénynek abban a csomagban kell lennie, amely importálja az annotációt az androidx.compose.runtime-ból. A függvény nevét ajánlott nagybetűvel írni — ez egy általánosan elfogadott konvenció a Compose közösségben, amely vizuálisan megkülönbözteti az UI komponenseket a szokványos függvényektől.
import androidx.compose.runtime.Composable
@Composable
fun Greeting(name: String) {
var count by remember { mutableStateOf(0) }
Column {
Text("Üdvözlöm, $name!")
Button(onClick = { count++ }) {
Text("$count alkalommal kattintva")
}
}
}
A Composable függvény paraméterei bármik lehetnek — primitív típusok, karakterláncok, lambdák és akár más Composable függvények is, amelyek a Slot API-n keresztül kerülnek átadásra. Ajánlott a paramétereket változhatatlanná tenni (val) a mellékhatások elkerülése érdekében a rekompozíció során. Minden változó adatot a Compose állapotmechanizmusain keresztül kell kezelni.
A Composable függvények nem képesek tetszőleges értéket visszaadni, mint a szokványos függvények — egyetlen feladatuk az UI fa egy részének felépítése vagy frissítése. Léteznek azonban speciális minták, mint a State Hoisting, ahol a Compose függvény állapotot és callback-eket fogad paramétereken keresztül, így tisztán és újrafelhasználhatóan marad.
A Compose rendszer számos szigorú korlátozást ír elő arra vonatkozóan, hogyan kell kinézniük és viselkedniük a Composable függvényeknek. Első szabály: egy Composable függvény csak más Composable függvényeket vagy mellékhatások nélküli szokványos függvényeket hívhat. Ez biztosítja a kompozíció kiszámíthatóságát és a Compose optimalizálások helyes működését.
A második szabály a végrehajtás sorrendjére vonatkozik. A Compose jogosult a Composable függvényeket bármilyen sorrendben meghívni, ezért az ilyen függvény törzsében lévő kód nem támaszkodhat a szomszédos függvények hívási sorrendjére. Minden Composable függvénynek önellátónak kell lennie az UI fában elfoglalt pozíciója szintjén.
Harmadik szabály — mellékhatások tiltása a Composable függvény törzsén belül. Az olyan műveletek, mint az adatbázisba írás, hálózati kérések küldése vagy külső változók módosítása csak a speciális LaunchedEffect, DisposableEffect vagy SideEffect effekteken belül végezhető. Ennek a szabálynak a megsértése kiszámíthatatlan viselkedéshez vezet a rekompozíciók során.
Negyedik szabály: A Composable függvényeknek idempotenseknek kell lenniük. Az ismételt meghívás ugyanazokkal az argumentumokkal ugyanazt az UI-t kell hogy eredményezze. Ez a követelmény szükséges a skipping optimalizálás helyes működéséhez, ahol a Compose kihagyja azon függvények újarajzolását, amelyek bemeneti adatai nem változtak.
// Helyes: tiszta Composable függvény mellékhatások nélkül
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
Card(modifier = Modifier.clickable { onClick() }) {
Text(text = user.name)
}
}
// Rossz: mellékhatás a törzsben
@Composable
fun WrongCard(userId: String) {
// val result = viewModel.loadUser(userId) // NEM ENGEDÉLYEZETT
Text("Betöltés...")
}
Nézzünk egy gyakorlati példát egy profil képernyő létrehozására a @Composable annotáció használatával. Itt bemutatjuk több Composable függvény kombinálását, az állapottal való munkát és a módosítókat — bármely Compose elrendezés kulcselemeit.
@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 = "Felhasználó #$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)
}
}
A példában minden Composable függvény felelős a képernyő saját részéért: a ProfileScreen kezeli az általános állapotot és a gyermek függvények kompozícióját, a ProfileHeader megjeleníti az avatart és a nevet, a StatsRow pedig a statisztikai blokkot. Ez a megközelítés követi az egységes felelősség elvét és egyszerűsíti a komponensek újrafelhasználását.
A Jetpack Compose három fő típusú Composable függvényt tartalmaz. Az első típus — konténerek (Row, Column, Box, LazyColumn), amelyek meghatározzák a gyermek elemek elhelyezését. A második — megjelenítő elemek (Text, Image, Icon, Button), amelyek konkrét UI komponenseket renderelnek. A harmadik — egyéni Composable függvények, amelyek a beépített komponenseket újrafelhasználható blokkokba kombinálják.
A konténerek abban különböznek a szokványos elemektől, hogy fogadnak egy content lambdát — az utolsó paramétert, amely @Composable () -> Unit típusú. Pontosan ez a mechanizmus teszi lehetővé a beágyazott UI fák építését: minden konténer létrehoz egy gyermek kompozíciót a saját kontextusával és memóriaterületével.
Az egyéni Composable függvények két altípusra oszlanak: okos (smart) és buta (dumb). Az okos függvények kezelik az állapotot és a logikát — tartalmazzák a remember, LaunchedEffect és egyéb Compose API-k hívásait. A buta függvények minden adatot paramétereken keresztül kapnak és csak megjelenítik azokat. Az okos és buta komponensekre bontás javítja a tesztelhetőséget és a kód újrafelhasználását.
| Típus | Példa | Cél |
|---|---|---|
| Konténer | Column, Row, Box | Gyermek elemek elhelyezésének kezelése |
| Elem | Text, Image, Button | Tartalom megjelenítése és bemenet feldolgozása |
| Egyéni | ProfileCard, UserList | Standard komponensek kombinációja |
A @Composable annotáció fő előnye — az újrafelhasználható UI komponensek létrehozásának lehetősége öröklődés és összetett osztályhierarchiák nélkül. Ellentétben a View rendszerrel, ahol minden egyéni elem egy Java osztály konstruktorokkal történő létrehozását igényelte, egy Composable komponens egyszerűen egy Kotlin függvény paraméterekkel.
Az újrafelhasználhatóság biztosítására a Slot API mintát alkalmazzák, ahol a Composable függvény content lambdákat fogad az elrendezése különböző területeihez. Például a Card komponens külön content-et fogadhat a fejléchez, a törzshöz és az alsó részhez, ami univerzálissá teszi az alkalmazás bármely képernyőjéhez.
A módosítók (Modifier) kulcsszerepet játszanak az újrafelhasználásban: lehetővé teszik a távolságok, méretek, kattintások és animációk beállítását anélkül, hogy magát a komponenst módosítanánk. Ajánlott mindig átadni a Modifier-t paraméterként egy Composable függvénynek alapértelmezett értékkel: Modifier = Modifier — ez a Google hivatalos könyvtáraiban elfogadott standard gyakorlat.
@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()
}
}
}
A Slot API-nak köszönhetően a SectionCard komponens különböző képernyőkön használható különböző tartalommal — űrlapokkal, listákkal, szöveges blokkokkal. A módosítók és a Slot API kombinációja maximálisan rugalmassá teszi a Compose komponenseket anélkül, hogy elveszítenék a Kotlin által biztosított típusbiztonságot.
Gyakran Ismételt Kérdések
A @Composable függvény a kompozíció kontextusában fut és képes állapotot olvasni, automatikusan újraindulva annak változásakor. A szokványos Kotlin függvények nem férnek hozzá az állapotkövető mechanizmusokhoz és nem vesznek részt az UI fa építésében.
Nem, a Composable függvények csak más Composable függvényekből hívhatók meg, mivel speciális kompozíciós kontextus szükséges. A Compose kód szokványos Kotlinnal való integrálásához a setContent { } metódust használjuk Activity-ben vagy ComposeView-t a View rendszerben.
Ez egy elnevezési konvenció a Compose közösségben. A nagybetű vizuálisan megkülönbözteti az UI komponenseket a szokványos függvényektől, követve az osztályok elnevezési szabályait. Ez nem fordítói követelmény, hanem a Google dokumentációban ajánlott gyakorlat.
Nincs korlátozás a számot illetően. A gyakorlatban egy nagy képernyő 50–100 Composable függvényt tartalmazhat, beleértve a beépített komponenseket (Text, Button) és egyénieket. A Compose optimalizálja a függvényfát és csak azokat hajtja végre, amelyek bemeneti adatai megváltoztak.
Általában a Composable függvények Unit-ot adnak vissza, mivel feladatuk az UI építése. Vannak azonban specializált függvények, mint a remember és a derivedStateOf, amelyek @Composable jelöléssel rendelkeznek és értéket adnak vissza. Ez kivétel, nem szabály.
Összefoglaló
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is