← ClaudeAtlas

android-compose-uilisted

Compose UI patterns for Android/KMP - stability, recomposition, side effects, lazy lists, animations, previews, accessibility, modifier extensions, and design system composables. Use this skill whenever writing or reviewing composables, optimizing recomposition, adding animations, creating previews, writing custom modifiers, structuring a design system, or making any Compose UI decision beyond the MVI/ViewModel layer. Trigger on phrases like "composable", "recomposition", "LaunchedEffect", "Modifier", "LazyColumn", "preview", "animation", "design system", "stability", "contentDescription", "graphicsLayer", "slot API", or "Compose performance".
lenorebreakneck630/claude-zero-to-hero-android-KMP · ★ 1 · Web & Frontend · score 64
Install: claude install-skill lenorebreakneck630/claude-zero-to-hero-android-KMP
# Android / KMP Compose UI Patterns ## Core Principle The UI is dumb. Composables render state and forward user actions — nothing more. All state lives in the ViewModel. All logic lives in the ViewModel, domain, or data layer. Compose code should contain zero business logic, zero data transformation, and minimal side effects. --- ## Stability & Recomposition Strong skipping mode is enabled by default in modern Compose — no explicit opt-in needed. Only annotate a state data class with `@Stable` when it contains fields the Compose compiler considers unstable (e.g., `List`, `Map`, `Set`, interfaces, or abstract types). If all fields are primitive types, `String`, or other stable types, no annotation is needed. ```kotlin // Needs @Stable — contains a List (unstable by default) @Stable data class NoteListState( val notes: List<NoteUi> = emptyList(), val isLoading: Boolean = false ) // No annotation needed — all fields are stable data class NoteDetailState( val title: String = "", val body: String = "", val isSaving: Boolean = false ) ``` --- ## State Ownership All state lives in the ViewModel. Do not use `remember` or `rememberSaveable` for application state — that belongs in the ViewModel's `StateFlow` and is surfaced via `collectAsStateWithLifecycle()`. The only exception is Compose-internal state that the framework requires you to hold in composition, such as `LazyListState`, `ScrollState`, or `PagerState`. For these, use `remember*` as needed: