Composables, State & Layout Basics
Declarative UI
You describe WHAT the UI looks like for a given state; Compose figures out HOW to update it — the same paradigm shift as React (vs. jQuery) or SwiftUI (vs. UIKit), replacing imperative textView.setText(...) calls.
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Column(modifier = Modifier.padding(16.dp)) {
Text("Count: $count")
Button(onClick = { count++ }) {
Text("Increment")
}
}
}
@Preview
@Composable
fun CounterPreview() {
Counter()
}remember{} keeps a value across recompositions (without it, state resets on every re-run). mutableStateOf() makes reading/writing trigger recomposition. The by delegate lets you use count directly instead of count.value. @Preview renders live in Android Studio, no build/deploy needed.
Layout Composables
Column { /* vertical, like LinearLayout(vertical) */ }
Row { /* horizontal */ }
Box { /* stacked, like FrameLayout */ }
Modifier
.fillMaxWidth()
.padding(16.dp)
.background(Color.Blue)
.clickable { onClick() }
// modifier order can affect the resulting layoutLazyColumn & Scaffold
LazyColumn only composes visible items (plus a small buffer) — Compose's RecyclerView equivalent for large/scrollable lists. Scaffold provides standard slots (top app bar, FAB, bottom nav, content) so they compose correctly without manual padding math.
ViewModel for Surviving Configuration Changes
Plain remember state doesn't survive an Activity recreation (like screen rotation) by default — a ViewModel holds state/logic scoped to the right lifecycle instead, separate from Composable functions which can be recreated more often.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free