@Composable: wat is het, Compose-annotatie en toepassingsgebied

Auteur: IT Sectr Gepubliceerd: 2026-06-27 Leestijd: 8 min

De @Composable-annotatie — het fundamentele element van Jetpack Compose dat een gewone Kotlin-functie omzet in een declaratief bouwblok voor de gebruikersinterface. Zonder deze annotatie kan geen enkel scherm worden gemaakt in moderne Android-ontwikkeling. Volgens Google Android Developers, 2026 gebruikt meer dan 80% van de nieuwe projecten in Kotlin Compose voor het bouwen van UI, en is @Composable de meest gebruikte annotatie in het ecosysteem.

Belangrijkste

  • @Composable — Kotlin-annotatie waarmee een functie UI declaratief kan beschrijven
  • Composable-functies kunnen alleen andere Composable-functies aanroepen, met inachtneming van de compositiecontext
  • Herstarten van Composable-functies gebeurt bij wijziging van invoerparameters of status
  • Aanroepvolgorde van Composable-functies is niet gegarandeerd — Compose optimaliseert herbouw van UI
  • Naamgeving van Composable-functies volgt PascalCase-regel, zoals alle componenten in Compose

Wat is @Composable in Jetpack Compose

@Composable — is een annotatie van de programmeertaal Kotlin die een functie markeert als bestemd voor het beschrijven van de gebruikersinterface in het Jetpack Compose-framework. Wanneer de Kotlin-compiler deze annotatie tegenkomt, genereert hij extra code waarmee de functie kan werken in de context van compositie — het systeem voor UI-boombeheer.

De @Composable-annotatie werd door Google geïntroduceerd in 2021 samen met de eerste stabiele versie van Jetpack Compose 1.0. Vóór de komst ervan werd de ontwikkeling van interfaces voor Android uitsluitend gedaan via XML-opmaak en het View-systeem. @Composable veranderde de aanpak radicaal: in plaats van UI te beschrijven in een apart opmaakbestand, schrijft de programmeur de interface rechtstreeks in Kotlin.

Het belangrijkste verschil tussen @Composable en gewone Kotlin-functies — het vermogen om statuswijzigingen te lezen en erop te reageren. Wanneer een variabele die een Composable-functie leest van waarde verandert, plant het systeem automatisch een herstart (recompositie) van die functie. Dit bevrijdt de programmeur van handmatige UI-updates via findViewById en setText.

De interne mechanica van @Composable is gebaseerd op het concept van een slot — een speciaal geheugengebied dat voor elke functie binnen de compositie wordt toegewezen. In dit slot worden de waarden opgeslagen die aan de functie zijn doorgegeven, evenals de service-informatie die nodig is voor vergelijking bij volgende aanroepen.

Een Composable-functie declareren

Om een Composable-functie te declareren, volstaat het om de @Composable-annotatie toe te voegen voor het sleutelwoord fun. De functie moet zich in een pakket bevinden dat de annotatie importeert uit androidx.compose.runtime. De functienaam wordt aanbevolen met een hoofdletter te schrijven — dit is een algemeen aanvaarde conventie in de Compose-gemeenschap die UI-componenten visueel onderscheidt van gewone functies.

kotlin
import androidx.compose.runtime.Composable

@Composable
fun Greeting(name: String) {
    var count by remember { mutableStateOf(0) }
    Column {
        Text("Hallo, $name!")
        Button(onClick = { count++ }) {
            Text("$count keer geklikt")
        }
    }
}

De parameters van een Composable-functie kunnen van alles zijn — primitieve typen, strings, lambda's en zelfs andere Composable-functies die via de Slot API worden doorgegeven. Het wordt aanbevolen om parameters onveranderlijk (val) te maken om bijwerkingen bij recompositie te voorkomen. Alle veranderlijke gegevens moeten worden beheerd via de statusechanismen van Compose.

Composable-functies kunnen geen willekeurige waarden retourneren zoals gewone functies — hun enige taak is het bouwen of bijwerken van een fragment van de UI-boom. Er bestaan echter speciale patronen zoals State Hoisting, waarbij een Compose-functie status en callbacks via parameters ontvangt, zuiver en herbruikbaar blijft.

Regels voor Composable-functies in Kotlin

Het Compose-systeem legt verschillende strikte beperkingen op aan hoe Composable-functies eruit moeten zien en zich moeten gedragen. Eerste regel: een Composable-functie kan alleen andere Composable-functies of gewone functies zonder bijwerkingen aanroepen. Dit zorgt voor voorspelbaarheid van de compositie en correcte werking van Compose-optimalisaties.

Tweede regel betreft de uitvoeringsvolgorde. Compose heeft het recht om Composable-functies in willekeurige volgorde aan te roepen, dus code in de body van zo'n functie mag niet vertrouwen op de aanroepvolgorde van naburige functies. Elke Composable-functie moet zelfvoorzienend zijn op het niveau van zijn positie in de UI-boom.

Derde regel — verbod op bijwerkingen binnen de body van een Composable-functie. Bewerkingen zoals schrijven naar een database, het verzenden van netwerkverzoeken of het wijzigen van externe variabelen mogen alleen worden uitgevoerd binnen speciale effecten LaunchedEffect, DisposableEffect of SideEffect. Overtreding van deze regel leidt tot onvoorspelbaar gedrag bij recomposities.

Vierde regel: Composable-functies moeten idempotent zijn. Herhaalde aanroep met dezelfde argumenten moet dezelfde UI opleveren. Deze vereiste is noodzakelijk voor correcte werking van de skipping-optimalisatie, waarbij Compose het opnieuw tekenen overslaat van functies waarvan de invoergegevens niet zijn veranderd.

kotlin
// Correct: zuivere Composable-functie zonder bijwerkingen
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
    Card(modifier = Modifier.clickable { onClick() }) {
        Text(text = user.name)
    }
}

// Fout: bijwerking in de body
@Composable
fun WrongCard(userId: String) {
    // val result = viewModel.loadUser(userId)  // NIET TOEGESTAAN
    Text("Laden...")
}

Voorbeelden van @Composable-gebruik

Laten we een praktisch voorbeeld bekijken van het maken van een profielscherm met de @Composable-annotatie. Hier demonstreren we het combineren van meerdere Composable-functies, werken met status en modificatoren — sleutelelementen van elke Compose-indeling.

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 = "Gebruiker #$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)
    }
}

In het voorbeeld is elke Composable-functie verantwoordelijk voor zijn deel van het scherm: ProfileScreen beheert de algemene status en compositie van de onderliggende functies, ProfileHeader toont de avatar en naam, en StatsRow — het blok met statistieken. Deze aanpak volgt het principe van enkele verantwoordelijkheid en vereenvoudigt herbruikbaarheid van componenten.

Soorten Composable-functies en hun doel

In Jetpack Compose bestaan drie hoofdtypen Composable-functies. Het eerste type — containers (Row, Column, Box, LazyColumn) die de plaatsing van onderliggende elementen bepalen. Het tweede — weergave-elementen (Text, Image, Icon, Button) die specifieke UI-componenten renderen. Het derde — aangepaste Composable-functies die ingebouwde componenten combineren in herbruikbare blokken.

Containers verschillen van gewone elementen doordat ze een content-lambda accepteren — de laatste parameter van het type @Composable () -> Unit. Precies dit mechanisme maakt het mogelijk om geneste UI-bomen te bouwen: elke container creëert een onderliggende compositie met zijn eigen context en geheugengebied.

Aangepaste Composable-functies zijn onderverdeeld in twee subtypes: slimme (smart) en domme (dumb). Slimme functies beheren status en logica — ze bevatten aanroepen naar remember, LaunchedEffect en andere Compose API's. Domme functies ontvangen alle gegevens via parameters en geven ze alleen weer. Verdeling in slimme en domme componenten verbetert testbaarheid en herbruikbaarheid van code.

TypeVoorbeeldDoel
ContainerColumn, Row, BoxBeheer van plaatsing onderliggende elementen
ElementText, Image, ButtonWeergave van inhoud en verwerking van invoer
AangepastProfileCard, UserListCombinatie van standaardcomponenten

@Composable en herbruikbaarheid van componenten

Het belangrijkste voordeel van de @Composable-annotatie — de mogelijkheid om herbruikbare UI-componenten te maken zonder overerving en complexe klassehiërarchieën. In tegenstelling tot het View-systeem, waar elk aangepast element het maken van een Java-klasse met constructors vereiste, is een Composable-component gewoon een Kotlin-functie met parameters.

Om herbruikbaarheid te garanderen, wordt het Slot API-patroon toegepast, waarbij een Composable-functie content-lambda's ontvangt voor verschillende delen van zijn lay-out. Een Card-component kan bijvoorbeeld afzonderlijke content ontvangen voor koptekst, body en onderste gedeelte, waardoor het universeel is voor alle schermen van de applicatie.

Modifiers (Modifier) spelen een sleutelrol in herbruikbaarheid: ze maken het mogelijk om tussenruimtes, afmetingen, klikken en animaties aan te passen zonder de component zelf te wijzigen. Het wordt aanbevolen om altijd Modifier als parameter van een Composable-functie door te geven met standaardwaarde: Modifier = Modifier — dit is een standaardpraktijk die in officiële Google-bibliotheken is aangenomen.

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

Dankzij Slot API kan de SectionCard-component worden gebruikt op verschillende schermen met verschillende inhoud — formulieren, lijsten, tekstblokken. Combinatie van modifiers en Slot API maakt Compose-componenten maximaal flexibel zonder verlies van typeveiligheid die Kotlin biedt.

Veelgestelde vragen

Waarin verschilt @Composable van een gewone Kotlin-functie?

Een @Composable-functie wordt uitgevoerd in de compositiecontext en kan status lezen, waarbij deze automatisch opnieuw wordt gestart bij wijziging. Gewone Kotlin-functies hebben geen toegang tot statusvolgmechanismen en nemen niet deel aan het bouwen van de UI-boom.

Kan een Composable-functie vanuit een gewone functie worden aangeroepen?

Nee, Composable-functies kunnen alleen vanuit andere Composable-functies worden aangeroepen, omdat een speciale compositiecontext vereist is. Voor integratie van Compose-code met gewoon Kotlin wordt de methode setContent { } in Activity of ComposeView in het View-systeem gebruikt.

Waarom worden Composable-functies met een hoofdletter geschreven?

Dit is een naamgevingsconventie in de Compose-gemeenschap. Hoofdletter onderscheidt visueel UI-componenten van gewone functies, volgens de naamgevingsregels voor klassen. Dit is geen compilervereiste, maar een aanbevolen praktijk in Google-documentatie.

Hoeveel Composable-functies kunnen op één scherm staan?

Er is geen limiet aan het aantal. In de praktijk kan een groot scherm 50–100 Composable-functies bevatten, inclusief ingebouwde componenten (Text, Button) en aangepaste. Compose optimaliseert de functieboom en voert alleen die uit waarvan de invoergegevens zijn gewijzigd.

Kan een Composable-functie een waarde retourneren?

Gewoonlijk retourneren Composable-functies Unit, omdat hun taak het bouwen van UI is. Er bestaan echter gespecialiseerde functies zoals remember en derivedStateOf die zijn gemarkeerd met @Composable en waarden retourneren. Dit is een uitzondering, geen regel.

Samenvatting

  • @Composable — annotatie voor declaratieve beschrijving van UI in Jetpack Compose
  • Composable-functies worden alleen aangeroepen binnen andere Composable-functies in een speciale context
  • Idempotentie — elke herhaalde uitvoering met dezelfde argumenten geeft dezelfde UI
  • Bijwerkingen zijn verboden in de functie-body — alleen via LaunchedEffect en SideEffect
  • Slot API en Modifier zorgen voor herbruikbaarheid van componenten zonder overerving
  • Containerfuncties (Row, Column, LazyColumn) accepteren content-lambda's voor geneste elementen
  • Aanbeveling: geef Modifier door als parameter van elke aangepaste Composable-functie met standaardwaarde

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook