| name | jetpack-compose |
| description | Jetpack Compose patterns for declarative UI, state management, theming, animations, and performance optimization. |
Jetpack Compose Patterns
Modern declarative UI patterns for Android.
State Management
State Hoisting
@Composable
fun Counter(
count: Int,
onIncrement: () -> Unit,
modifier: Modifier = Modifier
) {
Row(modifier = modifier) {
Text("Count: $count")
Button(onClick = onIncrement) {
Text("+")
}
}
}
@Composable
fun CounterScreen() {
var count by rememberSaveable { mutableStateOf(0) }
Counter(
count = count,
onIncrement = { count++ }
)
}
Remember Variants
val alpha by remember { mutableStateOf(1f) }
var count by rememberSaveable { mutableStateOf(0) }
val animation = remember(itemId) { Animatable(0f) }
val isValid by remember {
derivedStateOf { email.isNotBlank() && password.length >= 8 }
}
Composition Patterns
Slot API
@Composable
fun AppBar(
title: @Composable () -> Unit,
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {}
) {
TopAppBar(
title = { title() },
navigationIcon = { navigationIcon() },
actions = actions
)
}
AppBar(
title = { Text("Home") },
navigationIcon = { IconButton(onClick = {}) { Icon(Icons.Default.Menu, null) } },
actions = {
IconButton(onClick = {}) { Icon(Icons.Default.Search, null) }
}
)
Modifier Pattern
@Composable
fun CustomButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
content: @Composable RowScope.() -> Unit
) {
Button(
onClick = onClick,
modifier = modifier,
enabled = enabled,
content = content
)
}
Side Effects
LaunchedEffect
@Composable
fun HomeScreen(viewModel: HomeViewModel) {
LaunchedEffect(Unit) {
viewModel.loadData()
}
LaunchedEffect(userId) {
viewModel.loadUser(userId)
}
}
DisposableEffect
@Composable
fun LifecycleObserver(onResume: () -> Unit) {
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME) onResume()
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
}
Theming
Material 3
@Composable
fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colorScheme = if (darkTheme) DarkColorScheme else LightColorScheme
MaterialTheme(
colorScheme = colorScheme,
typography = AppTypography,
content = content
)
}
val backgroundColor = MaterialTheme.colorScheme.surface
val textStyle = MaterialTheme.typography.bodyLarge
Lists
LazyColumn
LazyColumn {
items(
items = users,
key = { it.id }
) { user ->
UserItem(user = user)
}
}
Animations
Animate Values
val alpha by animateFloatAsState(
targetValue = if (visible) 1f else 0f,
animationSpec = tween(durationMillis = 300)
)
val size by animateDpAsState(
targetValue = if (expanded) 200.dp else 100.dp
)
AnimatedContent
AnimatedContent(
targetState = state,
transitionSpec = {
fadeIn() togetherWith fadeOut()
}
) { targetState ->
when (targetState) {
is Loading -> LoadingContent()
is Success -> SuccessContent(targetState.data)
is Error -> ErrorContent()
}
}
Remember: Compose is declarative. Describe the UI, don't command it.