Jetpack Compose in mobiele ontwikkeling: wat is het, kernconcepten en hoe het werkt

Auteur: IT Sectr Gepubliceerd: 2026-07-05 Leestijd: 10 min
Jetpack Compose — een modern UI-framework voor Android van Google. Volgens Google Compose Docs (2025) wordt Compose gebruikt in 60% van de nieuwe Android-projecten. Inzicht in @Composable, Recomposition en State Hoisting is de basis voor productief werken met Compose.

Belangrijkste punten

  • @Composable — annotatie voor UI-functies. Composition — aanroepen van Composable-functies. Recomposition — herstart bij statuswijziging.
  • State Hoisting — status naar de ouder tillen. State down, events up. Herbruikbare en testbare componenten.
  • remember + mutableStateOf — lokale status. remember behoudt waarde tussen recomposities.
  • Modifier — keten van modifiers (padding, size, clickable). Volgorde is belangrijk.
  • NavController + NavHost — navigatie. LaunchedEffect/DisposableEffect — bijwerkingen.

Jetpack Compose Basis (@Composable, Composition, Recomposition)

@Composable — annotatie die een functie omzet in Composable. Composable-functies zijn UI-bouwstenen. Ze retourneren geen View, ze zenden elementen uit naar Composition. Composition — een UI-boom opgebouwd uit aanroepen van Composable-functies. Compose vergelijkt de nieuwe boom met de oude en werkt alleen de gewijzigde delen bij.

Recomposition

Recomposition — herstart van Composable-functies bij statuswijziging. Compose volgt welke statussen in elke functie worden gelezen. Wanneer een status verandert, herstart Compose alleen de functies die die status lezen (Smart Recomposition). Recomposition is optimistisch: kan meerdere keren worden uitgevoerd, dus functies moeten puur zijn (zonder bijwerkingen). Bijwerkingen gaan in LaunchedEffect of DisposableEffect. Composable-functies kunnen niet suspend zijn. Ze worden aangeroepen vanuit andere Composable-functies. Aanroepvolgorde is niet gegarandeerd (Compose kan herordenen).

kotlin
// Composable-voorbeeld met State Hoisting en LazyColumn
@Composable
fun ItemList(
    items: List<String>,
    onItemClick: (String) -> Unit
) {
    LazyColumn(
        modifier = Modifier.fillMaxSize()
    ) {
        items(items) { item ->
            Card(
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable { onItemClick(item) }
                    .padding(8.dp)
            ) {
                Text(
                    text = item,
                    style = MaterialTheme.typography.bodyLarge
                )
            }
        }
    }
}

@Composable
fun MainScreen() {
    var text by remember { mutableStateOf("") }
    val items = listOf("Item 1", "Item 2", "Item 3")

    Scaffold(
        topBar = {
            TopAppBar(title = { Text("Compose App") })
        }
    ) { padding ->
        ItemList(
            items = items,
            onItemClick = { selected -> text = selected }
        )
    }
}

Composition — declaratieve boom. Recomposition — slimme herstart. IT Sectr raadt aan om type stabiliteit te bewaken — instabiele types veroorzaken overmatige recompositie.

CompositionLocal

CompositionLocal — impliciete gegevensoverdracht in Compose. Analoog aan @Environment in SwiftUI. CompositionLocalProvider — waarde instellen. current — lezen. Gebruikt voor: Theme (MaterialTheme), ContentScale, Density. Statische CompositionLocal — voor configuratie zonder wijzigingen. Dynamische CompositionLocal — voor veranderlijke waarden (thema's). IT Sectr raadt aan CompositionLocal te gebruiken voor globale configuraties en expliciete parameters voor gegevens.

Status (remember, mutableStateOf, State Hoisting)

remember — behoudt waarde tussen recomposities. mutableStateOf — creëert waarneembare status (MutableState<T>). Bij wijziging wordt recompositie geactiveerd. State Hoisting — patroon: status wordt naar de bovenliggende component getild, kind ontvangt waarde + callback. State (onveranderlijk) — alleen lezen. MutableState — lezen + schrijven. rememberSaveable — blijft behouden bij rotatie/procesbeëindiging.

State Hoisting

State Hoisting — principe: state down, events up. Status wordt opgeslagen in de ouder en doorgegeven aan kindcomponenten via parameters. Kindcomponenten melden wijzigingen via lambda's (callback). Voordelen: herbruikbaarheid, testbaarheid, enkele bron van waarheid. Voorbeeld: in plaats dat MyTextField zijn eigen status opslaat, slaat de ouder de string op en geeft deze door via value + onValueChange.

Afgeleide status

derivedStateOf — berekende status, wordt alleen herberekend wanneer afhankelijkheden veranderen. Gebruikt voor filteren, converteren, valideren. snapshotFlow — converteert State naar Flow. Gebruikt voor reactieve ketens. collectAsState — verzamelt Flow in State binnen Composable. IT Sectr raadt derivedStateOf aan voor berekende waarden en snapshotFlow voor het verbinden van State met coroutines.

Containers (Column, Row, Box, LazyColumn)

Column — verticale lay-out (analoog aan LinearLayout verticaal). Row — horizontale lay-out. Box — stapellay-out (analoog aan FrameLayout). LazyColumn — verticale scrollbare lijst met lui laden. LazyRow — horizontale scrollbare lijst. Scaffold — hoofdschemastructuur: TopAppBar, BottomBar, FloatingActionButton, Snackbar. TopAppBar — bovenste balk. BottomNavigation — onderste navigatie (NavigationBar in Material 3). Modifier — keten: .fillMaxWidth().padding(8.dp).clickable { }. De volgorde van modifiers is belangrijk — elke maakt een nieuwe wrapper.

LazyColumn Optimalisatie

LazyColumn — gevirtualiseerde lijst. Rendert alleen zichtbare elementen. Optimalisatie: 1) key — unieke sleutel voor item, 2) contentType — items groeperen op type, 3) itemContent — recompositie binnen item minimaliseren, 4) LazyVerticalGrid / LazyHorizontalGrid — voor rasters. LazyLayout — aangepaste luie lay-out. Paging 3 + Compose — paginering via collectAsLazyPagingItems. IT Sectr raadt key(item) aan voor alle LazyColumn voor voorspelbare recompositie.

Navigation Compose — navigatiebibliotheek. NavController — beheert de bestemmingsstack. NavHost — container voor de navigatiegraaf. composable("route") — bestemming registreren. navController.navigate("route") — navigeren. popBackStack() — teruggaan. Argumenten: composable("detail/{id}", arguments = listOf(navArgument("id") { type = NavType.StringType })). Deep linking via intentFilter. BottomNavigation — integratie met NavController: NavBarItem → navigate + popUpTo.

Meerdere back stacks — aparte back stack voor elk tabblad van BottomNavigation. SavedStateHandle — argumenten behouden bij procesbeëindiging. NavArgs — typeveilige argumenten (Kotlin 2.0+). Deep links — URL-schema's voor externe links. Predictive back gesture (Android 14+) — ondersteuning voor teruggebaar met voorbeeld. IT Sectr raadt aan NavArgs te gebruiken voor typeveiligheid en meerdere back stacks voor BottomNavigation.

Effecten (LaunchedEffect, DisposableEffect)

LaunchedEffect — start een suspend-blok in Composition. Geannuleerd bij verlaten van Composition. Herstart bij wijziging van keys. Gebruikt voor: gegevens laden, timers, animaties. DisposableEffect — voor bronnen die opschoning nodig hebben: onDispose { } — uitschrijven van listeners, verbindingen sluiten. SideEffect — synchroon effect (elke recompositie). Gebruikt voor: loggen, synchroniseren met niet-Compose-code. IT Sectr raadt LaunchedEffect aan voor het laden van gegevens en DisposableEffect voor opschoning.

Parameter Jetpack Compose SwiftUI
UI-beschrijving@Composable functie + ModifierView Protocol + @ViewBuilder
Statusremember + mutableStateOf@State, @StateObject
Status tillenState Hoisting@Binding
LijstLazyColumnList
NavigatieNavController + NavHostNavigationStack (iOS 16+)
EffectenLaunchedEffect, DisposableEffect.task{}, .onAppear{}
LayoutColumn, Row, BoxVStack, HStack, ZStack

Compose — functie + modifier. SwiftUI — struct + modifier. Concepten zijn vergelijkbaar, syntaxis is anders. IT Sectr raadt aan beide frameworks te leren — het begrijpen van de ene vergemakkelijkt het leren van de andere.

Effectpatronen

rememberCoroutineScope — toegang tot CoroutineScope buiten LaunchedEffect (bijv. bij klikken op knop). snapshotFlow — State omzetten naar Flow voor ketens. produceState — niet-Compose-bron omzetten naar State. animateFloatAsState en animateColorAsState — animaties via effecten. IT Sectr raadt rememberCoroutineScope aan voor UI-gebeurtenissen en LaunchedEffect voor automatisch laden.

Thema's (MaterialTheme, Material3)

MaterialTheme — globaal Compose-thema. Kleuren, typografie, vormen. MaterialTheme { } — omhult de hele app. Material3 (M3) — Google ontwerpsysteem 2023+. Dynamic Colors — aanpassing aan achtergrond (Android 12+). TextStyle — tekstconfiguratie: fontSize, fontWeight, lineHeight. Shape — hoeken afronden. Elevation — schaduwen. IT Sectr raadt standaard Material3 aan en Dynamic Colors voor moderne apparaten.

kotlin
@Composable
fun AppTheme(content: @Composable () -> Unit) {
    val colorScheme = if (isSystemInDarkTheme()) {
        darkColorScheme(
            primary = Color(0xFFBB86FC),
            secondary = Color(0xFF03DAC6)
        )
    } else {
        lightColorScheme(
            primary = Color(0xFF6200EE),
            secondary = Color(0xFF03DAC6)
        )
    }
    MaterialTheme(
        colorScheme = colorScheme,
        typography = Typography(
            bodyLarge = TextStyle(fontSize = 16.sp)
        )
    ) { content() }
}

Animaties (animate*, AnimatedVisibility)

animateFloatAsState — animeert Float-waarde. animateColorAsState — animeert kleur. animateDpAsState — animeert grootte. AnimatedVisibility — tonen/verbergen met .animateEnterExit(). AnimatedContent — animatie bij inhoudswijziging (crossfade, slide). updateTransition — animatie op basis van enum-status. Animatable — aangepaste animatie via Animatable-interface. IT Sectr raadt AnimatedVisibility aan voor lijsten en AnimatedContent voor schermovergangen.

kotlin
@Composable
fun AnimatedCounter(count: Int) {
    val animatedCount by animateFloatAsState(
        targetValue = count.toFloat(),
        animationSpec = spring(
            dampingRatio = Spring.DampingRatioMediumBouncy,
            stiffness = Spring.StiffnessLow
        )
    )

    AnimatedContent(targetState = count) { targetCount ->
        Text(
            text = "$targetCount",
            style = MaterialTheme.typography.displayLarge,
            modifier = Modifier.animateContentSize()
        )
    }
}

Testen (Compose UI Test)

Compose UI Test — testen van Compose-schermen. createComposeRule() — JUnit-regel. setContent { } — Composable instellen. onNodeWithText, onNodeWithTag, onNodeWithContentDescription — elementen vinden. performClick, performTextInput, performScrollTo — acties. assertIsDisplayed, assertTextEquals — beweringen. Semantics — Semantics-boom voor toegankelijkheid en tests. IdlingResource — wachten op asynchrone bewerkingen. Screenshot-tests — Papercuts, Roborazzi. IT Sectr raadt UI-tests aan voor elk scherm en unittesten voor ViewModel.

WindowSizeClass — aanpassing aan schermgrootte (Compact, Medium, Expanded). Gerelateerd aan responsieve Material3-lay-outs. Gebruikt in Adaptive Navigation Suite voor automatische omschakeling van BottomNavigation naar NavigationRail. IT Sectr raadt WindowSizeClass aan voor tablet- en desktop-Compose-aanpassing.

Paging 3 + Compose — pagineringsbibliotheek van Google. PagingData — paginastroom. PagingConfig — instellingen (pageSize, prefetchDistance). collectAsLazyPagingItems() — verzamelen in Compose. PagingSource — aangepaste bron. RemoteMediator — hybride laden (netwerk + DB). Paging 3 is de standaard voor lijsten met oneindig scrollen in Compose.

Veelgestelde vragen

Wat is @Composable in Jetpack Compose?

@Composable — annotatie voor UI-functies. Aanroepen van Composable-functies vormen Composition. Recomposition — herstart bij statuswijziging.

Wat is State Hoisting in Compose?

State Hoisting — status naar de ouder tillen. State down, events up. Herbruikbare en testbare componenten.

Wat is Recomposition in Jetpack Compose?

Recomposition — herstart van Composable-functies bij statuswijziging. Smart Recomposition — minimale functieset.

Hoe werken NavController en NavHost?

NavController — bestemmingsstack. NavHost — graafcontainer. composable("route") — registratie. navigate() — overgang.

Wat is het verschil tussen LaunchedEffect en DisposableEffect?

LaunchedEffect — suspend-blok met automatische annulering. DisposableEffect — bronnen met onDispose-opschoning.

Samenvatting

  • @Composable — UI-functies. Composition — UI-boom. Recomposition — slimme herstart.
  • remember + mutableStateOf — lokale status. rememberSaveable — voor rotatie.
  • State Hoisting — state down, events up. Basis van herbruikbare componenten.
  • Modifier — keten (volgorde belangrijk). Column, Row, Box — basiscontainers.
  • LazyColumn — efficiënte lijst. Scaffold — schermstructuur (TopBar, BottomBar, FAB).
  • NavController + NavHost — navigatie. composable() — routes. navigate() — overgangen.
  • LaunchedEffect — asynchrone effecten. DisposableEffect — opschoning. SideEffect — synchroon.

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