Quick reference for Kotlin syntax, Jetpack Compose composables, state and remember, Modifiers, Navigation Compose, coroutines, and Flow.
Jetpack ComposeKotlinCoroutinesState
Kotlin Syntax
Variables & Null Safety
val name = "Ada" // immutable
var count = 0 // mutable
val price: Double = 9.99 // explicit type
var nick: String? = null // nullable
val len = nick?.length ?: 0 // safe call + Elvis
nick?.let { use(it) } // run if non-null
val x = nick!! // throws if null (avoid)
Functions & Lambdas
fun add(a: Int, b: Int) = a + b // expression body
fun hi(name: String, p: String = "!") = "Hi $name$p"
hi(name = "Sam") // named arg
val square = { n: Int -> n * n } // lambda
list.filter { it % 2 == 0 } // implicit `it`
list.map { it * 2 }
list.forEach { println(it) }
Data & Sealed Classes
data class User(val id: Int, val name: String)
val u2 = u1.copy(name = "New") // copy
sealed interface UiState {
data object Loading : UiState
data class Success(val data: List<User>) : UiState
data class Error(val msg: String) : UiState
}
when (state) { // exhaustive
UiState.Loading -> …
is UiState.Success -> state.data
is UiState.Error -> state.msg
}
Compose Basics
@Composable
fun Greeting(name: String) {
Text(text = "Hello, $name!")
}
setContent { // in Activity.onCreate
AppTheme { Greeting("Android") }
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() = Greeting("Preview")
Layout Composables
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
Text("Top"); Text("Bottom")
}
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Default.Star, null); Text("Label")
}
Box(contentAlignment = Alignment.Center) {
Image(...); Text("Overlay")
}
Spacer(Modifier.height(16.dp))
LazyColumn {
items(users, key = { it.id }) { u -> UserRow(u) }
item { Footer() }
}
| Composable | Use |
| Column | Vertical stack |
| Row | Horizontal stack |
| Box | Overlay / z-stack |
| LazyColumn | Scrollable list |
| LazyRow | Horizontal list |
| LazyVerticalGrid | Grid of cells |
State & remember
var count by remember { mutableStateOf(0) }
count++ // triggers recomposition
// survives rotation / process recreation
var text by rememberSaveable { mutableStateOf("") }
// derived value, recomputed only when inputs change
val enabled by remember { derivedStateOf { text.isNotBlank() } }
// State hoisting: stateless child
@Composable
fun Field(value: String, onChange: (String) -> Unit) {
TextField(value = value, onValueChange = onChange)
}
// ViewModel + StateFlow
val state by vm.state.collectAsStateWithLifecycle()
| API | Survives |
| remember | Recomposition |
| rememberSaveable | + rotation / process death |
| ViewModel | + full config changes |
Modifiers
Modifier
.fillMaxWidth() // .fillMaxSize() / .size(48.dp)
.padding(16.dp) // order matters!
.background(color)
.clip(RoundedCornerShape(12.dp))
.border(1.dp, color)
.clickable { onClick() }
.weight(1f) // inside Row/Column
.align(Alignment.Center) // inside Box/Column/Row
.aspectRatio(16f / 9f)
Navigation
@Serializable object Home
@Serializable data class Details(val id: Int)
val nav = rememberNavController()
NavHost(nav, startDestination = Home) {
composable<Home> {
HomeScreen(onOpen = { nav.navigate(Details(it)) })
}
composable<Details> { entry ->
val args = entry.toRoute<Details>()
DetailsScreen(args.id)
}
}
nav.navigate(Details(7)) // go to
nav.popBackStack() // back
nav.navigate(Home) { popUpTo(Home) { inclusive = true } }
Coroutines & Flow
suspend fun load() = withContext(Dispatchers.IO) { api.get() }
viewModelScope.launch { _state.value = load() } // scoped, auto-cancels
// concurrent
coroutineScope {
val a = async { api.getA() }
val b = async { api.getB() }
combine(a.await(), b.await())
}
// Flow pipeline
queries
.debounce(300)
.filter { it.length >= 2 }
.distinctUntilChanged()
.mapLatest { repo.search(it) } // cancels previous
.collect { render(it) }
// StateFlow in a ViewModel
private val _s = MutableStateFlow<UiState>(UiState.Loading)
val s: StateFlow<UiState> = _s.asStateFlow()
Common Patterns
| Need | API |
| Run suspend work on key change | LaunchedEffect(key) |
| Setup / teardown | DisposableEffect |
| Callback from event handler | rememberCoroutineScope |
| Collect Flow lifecycle-aware | collectAsStateWithLifecycle() |
| Screen scaffolding | Scaffold { TopAppBar, FAB } |
| Theme colors / type | MaterialTheme.colorScheme |
| Type-safe HTTP | Retrofit suspend @GET |
| Get ViewModel in composable | viewModel() / hiltViewModel() |