Based on NowInAndroid Compose patterns.
- MUST hoist state to caller: Composable receives state + event callbacks
- MUST use
rememberfor expensive computations in Composable scope - MUST use
rememberSaveablefor state that survives configuration changes - MUST collect Flow with
collectAsStateWithLifecycle() - MUST NOT modify state directly inside Composable — emit events to ViewModel
// NIA pattern: Screen receives state, delegates actions
@Composable
fun ForYouScreen(
uiState: ForYouUiState,
onTopicCheckedChanged: (String, Boolean) -> Unit,
) { /*...*/ }- MUST use stable/immutable types for Composable parameters
- MUST annotate custom models with
@Immutableor@Stable - MUST use
key()in loops and dynamic lists - SHOULD use
derivedStateOffor values derived from frequently-changing state - MUST NOT allocate objects (lists, maps, lambdas) without
remember - MUST NOT perform side effects during composition
- MUST use
LaunchedEffectfor composition-scoped coroutine side effects - MUST use
DisposableEffectfor cleanup-required side effects - SHOULD use
rememberCoroutineScope()for user-triggered coroutines - MUST NOT call
viewModelScope.launchfrom Composable
- MUST accept
Modifieras first optional parameter - MUST keep Composables small — extract at ~50 lines
- MUST provide
@Previewwith sample data for public Composables - SHOULD separate stateful (container) and stateless (UI) Composables
- MUST NOT use mutable collections as Composable parameters
- MUST provide stable
keyinLazyColumn/LazyRowitems - MUST use
contentTypefor heterogeneous lists - MUST NOT nest
LazyColumninsideverticalScrollColumn — runtime crash
// NIA pattern: single LazyColumn with mixed content
LazyColumn {
item { Header() }
items(newsResources, key = { it.id }, contentType = { "newsResource" }) {
NewsResourceCard(it)
}
}- MUST use
MaterialThemetokens (colorScheme, typography, shapes) - MUST support light/dark theme
- MUST NOT hardcode colors, font sizes, or dimensions
- MUST use
ComposeViewto embed Compose in XML - MUST use
AndroidViewto embed XML Views in Compose - SHOULD migrate bottom-up: leaf components first, then containers
Skills: /compose-animation, /compose-performance, /compose-navigation, /compose-testing