@Composable: vad är det, Compose-annotering och tillämpningsområde

Författare: IT Sectr Publicerad: 2026-06-27 Lästid: 8 min

Annoteringen @Composable — den grundläggande delen av Jetpack Compose som omvandlar en vanlig Kotlin-funktion till en deklarativ byggsten för användargränssnittet. Utan denna annotering kan ingen skärm skapas i modern Android-utveckling. Enligt Google Android Developers, 2026 använder över 80% av nya projekt i Kotlin Compose för att bygga UI, och @Composable är den mest använda annoteringen i ekosystemet.

Huvudsakligt

  • @Composable — Kotlin-annotering som gör att en funktion kan beskriva UI deklarativt
  • Composable-funktioner kan bara anropa andra Composable-funktioner, med respekt för kompositionskontexten
  • Omstart av Composable-funktioner sker när indataparameterar eller tillstånd ändras
  • Anropsordning för Composable-funktioner garanteras inte — Compose optimerar ombyggnad av UI
  • Namngivning av Composable-funktioner följer PascalCase-regeln, som alla komponenter i Compose

Vad är @Composable i Jetpack Compose

@Composable — är en annotering i programmeringsspråket Kotlin som markerar en funktion som avsedd för att beskriva användargränssnittet i Jetpack Compose-ramverket. När Kotlin-kompilatorn stöter på denna annotering genererar den extra kod som gör att funktionen kan arbeta i kompositionskontexten — systemet för UI-trädshantering.

@Composable-annoteringen introducerades av Google 2021 tillsammans med den första stabila versionen av Jetpack Compose 1.0. Före dess utfördes utveckling av gränssnitt för Android uteslutande genom XML-markup och View-systemet. @Composable förändrade angreppssättet radikalt: istället för att beskriva UI i en separat markup-fil skriver programmeraren gränssnittet direkt i Kotlin.

Den största skillnaden mellan @Composable och vanliga Kotlin-funktioner — förmågan att läsa och reagera på tillståndsförändringar. När en variabel som en Composable-funktion läser ändrar värde, schemalägger systemet automatiskt en omstart (rekomposition) av den funktionen. Detta befriar programmeraren från manuell UI-uppdatering via findViewById och setText.

Den interna mekaniken i @Composable bygger på konceptet slot — ett speciellt minnesområde som tilldelas varje funktion inom kompositionen. I denna slot lagras värdena som skickats till funktionen, samt den serviceinformation som behövs för jämförelse vid efterföljande anrop.

Hur man deklarerar en Composable-funktion

För att deklarera en Composable-funktion räcker det att lägga till annoteringen @Composable före nyckelordet fun. Funktionen måste finnas i ett paket som importerar annoteringen från androidx.compose.runtime. Funktionsnamnet rekommenderas att skrivas med stor bokstav — detta är en allmänt accepterad konvention i Compose-gemenskapen som visuellt skiljer UI-komponenter från vanliga funktioner.

kotlin
import androidx.compose.runtime.Composable

@Composable
fun Greeting(name: String) {
    var count by remember { mutableStateOf(0) }
    Column {
        Text("Hej, $name!")
        Button(onClick = { count++ }) {
            Text("Klickat $count gånger")
        }
    }
}

Parametrarna för en Composable-funktion kan vara vad som helst — primitiva typer, strängar, lambdor och till och med andra Composable-funktioner som skickas via Slot API. Det rekommenderas att göra parametrar oföränderliga (val) för att undvika biverkningar vid rekomposition. Alla föränderliga data bör hanteras via Compose tillståndsmekanismer.

Composable-funktioner kan inte returnera godtyckliga värden som vanliga funktioner — deras enda uppgift är att bygga eller uppdatera en del av UI-trädet. Det finns dock speciella mönster som State Hoisting, där Compose-funktionen tar emot tillstånd och callbacks via parametrar och förblir ren och återanvändbar.

Regler för Composable-funktioner i Kotlin

Compose-systemet inför flera strikta begränsningar för hur Composable-funktioner ska se ut och bete sig. Första regeln: en Composable-funktion kan bara anropa andra Composable-funktioner eller vanliga funktioner utan biverkningar. Detta säkerställer förutsägbarhet i kompositionen och korrekt funktion av Compose-optimeringar.

Andra regeln gäller exekveringsordningen. Compose har rätt att anropa Composable-funktioner i vilken ordning som helst, därför ska koden i kroppen av en sådan funktion inte förlita sig på anropsordningen för angränsande funktioner. Varje Composable-funktion bör vara självförsörjande på nivån av sin position i UI-trädet.

Tredje regeln — förbud mot biverkningar inuti själva kroppen av en Composable-funktion. Operationer som att skriva till databas, skicka nätverksförfrågningar eller ändra externa variabler får endast utföras inuti speciella effekter som LaunchedEffect, DisposableEffect eller SideEffect. Brott mot denna regel leder till oförutsägbart beteende vid rekompositioner.

Fjärde regeln: Composable-funktioner bör vara idempotenta. Upprepat anrop med samma argument ska producera samma UI. Detta krav är nödvändigt för korrekt funktion av skipping-optimeringen, där Compose hoppar över omritning av funktioner vars indata inte har ändrats.

kotlin
// Rätt: ren Composable-funktion utan biverkningar
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
    Card(modifier = Modifier.clickable { onClick() }) {
        Text(text = user.name)
    }
}

// Fel: biverkning inuti kroppen
@Composable
fun WrongCard(userId: String) {
    // val result = viewModel.loadUser(userId)  // INTE TILLÅTET
    Text("Laddar...")
}

Exempel på @Composable-användning

Låt oss titta på ett praktiskt exempel på att skapa en profilsärm med hjälp av @Composable-annoteringen. Här demonstrerar vi kombinationen av flera Composable-funktioner, arbete med tillstånd och modifierare — nyckelelement i alla Compose-layouter.

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 = "Användare #$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)
    }
}

I exemplet är varje Composable-funktion ansvarig för sin del av skärmen: ProfileScreen hanterar det allmänna tillståndet och kompositionen av underordnade funktioner, ProfileHeader visar avatar och namn, och StatsRow — blocket med statistik. Detta tillvägagångssätt följer principen om enskilt ansvar och förenklar återanvändning av komponenter.

Typer av Composable-funktioner och deras syfte

I Jetpack Compose finns tre huvudtyper av Composable-funktioner. Första typen — behållare (Row, Column, Box, LazyColumn) som bestämmer placeringen av underordnade element. Andra — visningselement (Text, Image, Icon, Button) som renderar specifika UI-komponenter. Tredje — anpassade Composable-funktioner som kombinerar inbyggda komponenter till återanvändbara block.

Behållare skiljer sig från vanliga element genom att de accepterar en content-lambda — den sista parametern av typen @Composable () -> Unit. Det är just denna mekanism som möjliggör byggandet av nästlade UI-träd: varje behållare skapar en underordnad komposition med sin egen kontext och minnesområde.

Anpassade Composable-funktioner delas in i två undertyper: smarta (smart) och dumma (dumb). Smarta funktioner hanterar tillstånd och logik — de innehåller anrop till remember, LaunchedEffect och andra Compose API:er. Dumma funktioner tar emot all data via parametrar och visar bara upp dem. Uppdelningen i smarta och dumma komponenter förbättrar testbarhet och återanvändning av kod.

TypExempelSyfte
BehållareColumn, Row, BoxHantering av placering av underordnade element
ElementText, Image, ButtonVisning av innehåll och bearbetning av inmatning
AnpassadProfileCard, UserListKombination av standardkomponenter

@Composable och återanvändning av komponenter

Den största fördelen med @Composable-annoteringen — möjligheten att skapa återanvändbara UI-komponenter utan arv och komplexa klasshierarkier. Till skillnad från View-systemet, där varje anpassat element krävde skapandet av en Java-klass med konstruktorer, är en Composable-komponent helt enkelt en Kotlin-funktion med parametrar.

För att säkerställa återanvändning tillämpas mönstret Slot API, där Composable-funktionen tar emot content-lambdor för olika områden av sin layout. Till exempel kan Card-komponenten ta emot separat content för rubrik, kropp och nedre del, vilket gör den universell för alla skärmar i applikationen.

Modifierare (Modifier) spelar en nyckelroll i återanvändning: de möjliggör justering av mellanrum, storlekar, klick och animationer utan att ändra själva komponenten. Det rekommenderas att alltid skicka Modifier som parameter till en Composable-funktion med standardvärde: Modifier = Modifier — detta är en standardpraxis som antagits i Googles officiella bibliotek.

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()
        }
    }
}

Tack vare Slot API kan SectionCard-komponenten användas på olika skärmar med olika innehåll — formulär, listor, textblock. Kombinationen av modifierare och Slot API gör Compose-komponenter maximalt flexibla utan att förlora den typsäkerhet som Kotlin erbjuder.

Vanliga frågor

Vad skiljer @Composable från en vanlig Kotlin-funktion?

En @Composable-funktion körs i kompositionskontexten och kan läsa tillstånd, automatiskt omstartad vid dess ändring. Vanliga Kotlin-funktioner har inte tillgång till tillståndsuppföljningsmekanismer och deltar inte i byggandet av UI-trädet.

Kan en Composable-funktion anropas från en vanlig funktion?

Nej, Composable-funktioner kan bara anropas från andra Composable-funktioner, eftersom en speciell kompositionskontext krävs. För integration av Compose-kod med vanlig Kotlin används metoden setContent { } i Activity eller ComposeView i View-systemet.

Varför skrivs Composable-funktioner med stor bokstav?

Detta är en namngivningskonvention i Compose-gemenskapen. Stor bokstav skiljer visuellt UI-komponenter från vanliga funktioner, enligt klassernas namngivningsregler. Det är inget kompilatorkrav, men en rekommenderad praxis i Googles dokumentation.

Hur många Composable-funktioner kan finnas på en skärm?

Det finns ingen gräns för antalet. I praktiken kan en stor skärm innehålla 50–100 Composable-funktioner, inklusive inbyggda komponenter (Text, Button) och anpassade. Compose optimerar funktionsträdet och utför bara de vars indata har ändrats.

Kan en Composable-funktion returnera ett värde?

Vanligtvis returnerar Composable-funktioner Unit, eftersom deras uppgift är att bygga UI. Det finns dock specialiserade funktioner som remember och derivedStateOf som är märkta med @Composable och returnerar värden. Detta är ett undantag, inte en regel.

Sammanfattning

  • @Composable — annotering för deklarativ beskrivning av UI i Jetpack Compose
  • Composable-funktioner anropas endast inuti andra Composable-funktioner i en speciell kontext
  • Idempotens — varje upprepat utförande med samma argument ger samma UI
  • Biverkningar är förbjudna i funktionskroppen — endast via LaunchedEffect och SideEffect
  • Slot API och Modifier säkerställer återanvändning av komponenter utan arv
  • Behållarfunktioner (Row, Column, LazyColumn) accepterar content-lambdor för nästlade element
  • Rekommendation: skicka Modifier som parameter till varje anpassad Composable-funktion med standardvärde

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också