No,Category,Guideline,Description,Do,Don't,Code Good,Code Bad,Severity,Docs URL
1,State Management,Use remember for local state,remember preserves state across recompositions,Use remember { mutableStateOf() } for UI state,Create state without remember,val count = remember { mutableStateOf(0) },val count = mutableStateOf(0),Critical,https://developer.android.com/develop/ui/compose/state
2,State Management,Use rememberSaveable for configuration changes,rememberSaveable survives process death and config changes,Use rememberSaveable for user input,Use remember for data that should survive rotation,val text = rememberSaveable { mutableStateOf("") },val text = remember { mutableStateOf("") } for form data,High,https://developer.android.com/develop/ui/compose/state#restore-ui-state
3,State Management,Hoist state to caller,State hoisting makes composables reusable and testable,Pass state and event callbacks as parameters,Keep state internal when it should be shared,"fun Counter(count: Int, onIncrement: () -> Unit)",fun Counter() { var count = remember { mutableStateOf(0) } },High,https://developer.android.com/develop/ui/compose/state#state-hoisting
4,State Management,Use ViewModel for business logic state,ViewModel survives configuration changes and manages UI state,Collect Flow as State with collectAsState,Put business logic in composables,val uiState by viewModel.uiState.collectAsState(),var data = remember { fetchData() },Critical,https://developer.android.com/topic/libraries/architecture/viewmodel
5,State Management,Use derivedStateOf for computed values,derivedStateOf prevents unnecessary recompositions,Wrap expensive calculations in derivedStateOf,Compute values directly in composition,val filtered = remember { derivedStateOf { list.filter { it.active } } },val filtered = list.filter { it.active },High,https://developer.android.com/develop/ui/compose/state#derived-state
6,State Management,Use LaunchedEffect for coroutine side effects,LaunchedEffect runs coroutines tied to composition lifecycle,Use LaunchedEffect with proper keys,Launch coroutines without lifecycle awareness,"LaunchedEffect(userId) { loadUser(userId) }","scope.launch { loadUser(userId) }",Critical,https://developer.android.com/develop/ui/compose/side-effects#launchedeffect
7,State Management,Use DisposableEffect for cleanup,DisposableEffect handles setup and cleanup of resources,Return onDispose for cleanup logic,Forget to clean up resources,"DisposableEffect(key) { onDispose { cleanup() } }",LaunchedEffect without cleanup for listeners,High,https://developer.android.com/develop/ui/compose/side-effects#disposableeffect
8,State Management,Use SideEffect for non-Compose code,SideEffect runs after every successful recomposition,Sync Compose state to non-Compose code,Use SideEffect for suspending operations,SideEffect { analytics.log(screenName) },LaunchedEffect for synchronous callbacks,Medium,https://developer.android.com/develop/ui/compose/side-effects#sideeffect
9,State Management,Use snapshotFlow for converting State to Flow,snapshotFlow creates Flow from Compose State reads,Convert State changes to Flow for processing,Create manual flows from state,"snapshotFlow { scrollState.value }.collect { }",Flow that manually observes state changes,Medium,https://developer.android.com/develop/ui/compose/side-effects#snapshotflow
10,State Management,Use produceState for async data,produceState converts non-Compose state into Compose State,Load async data into composition,Use LaunchedEffect with separate state,"val data by produceState(initial) { value = loadData() }","var data by remember { mutableStateOf(null) }; LaunchedEffect { data = loadData() }",Medium,https://developer.android.com/develop/ui/compose/side-effects#producestate
11,Animation,Use animate*AsState for simple animations,animate*AsState automatically animates value changes,Use for single value animations,Use for complex coordinated animations,"val alpha by animateFloatAsState(if (visible) 1f else 0f, label = ""alpha"")","var alpha = if (visible) 1f else 0f",High,https://developer.android.com/develop/ui/compose/animation/value-based
12,Animation,Use Animatable for imperative control,Animatable provides coroutine-based animation control,Use when you need snapTo or animateTo,Use for simple state-driven animations,"val offset = remember { Animatable(0f) }; offset.animateTo(100f)","animateFloatAsState for gesture-driven animations",Medium,https://developer.android.com/develop/ui/compose/animation/value-based#animatable
13,Animation,Use AnimatedVisibility for enter/exit,AnimatedVisibility handles appear/disappear animations,Use for showing/hiding composables,Manually animate alpha for visibility,"AnimatedVisibility(visible) { Content() }","Box(Modifier.alpha(if (visible) 1f else 0f)) { Content() }",High,https://developer.android.com/develop/ui/compose/animation/composables-modifiers#animatedvisibility
14,Animation,Use AnimatedContent for content transitions,AnimatedContent animates between different content,Use for content that changes with animation,Use AnimatedVisibility for different content,"AnimatedContent(targetState) { state -> when(state) { } }","if (state) Content1() else Content2()",Medium,https://developer.android.com/develop/ui/compose/animation/composables-modifiers#animatedcontent
15,Animation,Use updateTransition for coordinated animations,updateTransition manages multiple animations together,Coordinate multiple property animations,Use separate animate*AsState for related animations,"val transition = updateTransition(state, label = ""box""); val size by transition.animateDp { }","val size by animateDpAsState(); val color by animateColorAsState()",Medium,https://developer.android.com/develop/ui/compose/animation/value-based#updatetransition
16,Animation,Use InfiniteTransition for looping animations,InfiniteTransition runs animations indefinitely,Use for loading indicators and attention,Use for one-time animations,"val alpha by rememberInfiniteTransition(label = ""pulse"").animateFloat(0f, 1f, infiniteRepeatable(tween(1000)))",LaunchedEffect with while(true) for animations,High,https://developer.android.com/develop/ui/compose/animation/value-based#infinitetransition
17,Animation,Use spring for natural motion,Spring animations feel natural and interruptible,Use spring as default animation spec,Use tween for all animations,"animateDpAsState(target, animationSpec = spring(dampingRatio = 0.7f))","animateDpAsState(target, animationSpec = tween(300))",Medium,https://developer.android.com/develop/ui/compose/animation/customize#spring
18,Animation,Use tween for precise timing,Tween provides duration-based easing animations,Use when exact duration is needed,Use for physics-based interactions,"animateFloatAsState(target, animationSpec = tween(300, easing = FastOutSlowInEasing))","spring for timed sequences",Medium,https://developer.android.com/develop/ui/compose/animation/customize#tween
19,Animation,Use keyframes for complex timing,Keyframes allow multi-stage animations with different timings,Define specific values at time points,Use for simple A to B animations,"keyframes { durationMillis = 1000; 0.5f at 200; 1f at 500 }",Multiple chained tweens,Medium,https://developer.android.com/develop/ui/compose/animation/customize#keyframes
20,Animation,Optimize for 120Hz displays,Modern devices support high refresh rates,Use lightweight animations and avoid overdraw,Ignore frame rate optimization,Modifier.graphicsLayer { } for GPU-accelerated transforms,Complex recompositions during animation,High,https://developer.android.com/develop/ui/compose/performance
21,Animation,Always provide animation labels,Labels help with debugging and tooling,Add label parameter to animations,"Leave label as empty string","animateFloatAsState(value, label = ""fadeIn"")","animateFloatAsState(value, label = """")",Low,https://developer.android.com/develop/ui/compose/tooling/animation
22,Animation,Use Modifier.animateContentSize,animateContentSize smoothly animates size changes,Use for expandable content,Manually animate height changes,Modifier.animateContentSize(),"var height by animateDpAsState(if (expanded) 200.dp else 100.dp)",High,https://developer.android.com/develop/ui/compose/animation/composables-modifiers#animatecontentsize
23,Animation,Use crossfade for simple content swap,Crossfade provides simple fade transition between content,Use for simple content changes,Use for complex enter/exit animations,"Crossfade(targetState) { state -> Content(state) }",AnimatedContent for simple fades,Low,https://developer.android.com/develop/ui/compose/animation/composables-modifiers#crossfade
24,Animation,Handle gesture animations with Animatable,Animatable works well with gesture velocities,Pass velocity to animateTo after gestures,Ignore velocity in fling gestures,"animatable.animateTo(target, initialVelocity = velocity)","animatable.animateTo(target)",Medium,https://developer.android.com/develop/ui/compose/animation/value-based#animatable
25,Animation,Use shared element transitions,Shared elements create visual continuity between screens,Use for navigation transitions,Create custom position animations,"SharedTransitionLayout { AnimatedContent { SharedElement() } }",Manual position animation between screens,Medium,https://developer.android.com/develop/ui/compose/animation/shared-elements
26,Layouts,Use Column for vertical layouts,Column arranges children vertically,Use Column for vertical lists of items,Use nested Boxes for vertical layout,"Column { Text(""A""); Text(""B"") }","Box { Text(""A""); Box(Modifier.offset(y = 20.dp)) { Text(""B"") } }",High,https://developer.android.com/develop/ui/compose/layouts/basics#standard-layouts
27,Layouts,Use Row for horizontal layouts,Row arranges children horizontally,Use Row for horizontal arrangements,Use nested Boxes for horizontal layout,"Row { Icon(); Text(""Label"") }","Box { Icon(); Box(Modifier.offset(x = 24.dp)) { Text(""Label"") } }",High,https://developer.android.com/develop/ui/compose/layouts/basics#standard-layouts
28,Layouts,Use Box for stacking,Box stacks children on top of each other,Use Box for overlays and positioning,Use ConstraintLayout for simple stacking,"Box { Image(); Text(modifier = Modifier.align(Alignment.BottomEnd)) }",ConstraintLayout for simple overlay,Medium,https://developer.android.com/develop/ui/compose/layouts/basics#standard-layouts
29,Layouts,Use LazyColumn for long lists,LazyColumn only composes visible items,Use for scrollable lists of items,Use Column with verticalScroll for large lists,"LazyColumn { items(data) { Item(it) } }","Column(Modifier.verticalScroll(rememberScrollState())) { data.forEach { Item(it) } }",Critical,https://developer.android.com/develop/ui/compose/lists
30,Layouts,Use LazyRow for horizontal scrolling lists,LazyRow composes only visible horizontal items,Use for horizontal carousels,Use Row with horizontalScroll for many items,"LazyRow { items(images) { ImageCard(it) } }","Row(Modifier.horizontalScroll(rememberScrollState())) { images.forEach { ImageCard(it) } }",High,https://developer.android.com/develop/ui/compose/lists
31,Layouts,Use LazyGrid for grid layouts,LazyVerticalGrid and LazyHorizontalGrid for efficient grids,Use for photo galleries and product grids,Use nested LazyRows or manual grid calculation,"LazyVerticalGrid(columns = GridCells.Fixed(2)) { items(photos) { } }","LazyColumn { items(photos.chunked(2)) { row -> Row { } } }",High,https://developer.android.com/develop/ui/compose/lists#grids
32,Layouts,Provide keys for LazyColumn items,Keys help Compose track items efficiently,Use unique stable keys for items,Rely on index-based keys for dynamic lists,"LazyColumn { items(users, key = { it.id }) { } }","LazyColumn { items(users) { } }",High,https://developer.android.com/develop/ui/compose/lists#item-keys
33,Layouts,Use ConstraintLayout for complex layouts,ConstraintLayout enables flexible constraint-based positioning,Use for complex relative positioning,Use for simple linear layouts,"ConstraintLayout { createRefs(); Box(Modifier.constrainAs(ref) { }) }","ConstraintLayout { Column { Row { } } }",Medium,https://developer.android.com/develop/ui/compose/layouts/constraintlayout
34,Layouts,Use Scaffold for Material screens,Scaffold provides Material Design layout structure,Use for screens with app bars and FABs,Build scaffold structure manually,"Scaffold(topBar = { TopAppBar() }, floatingActionButton = { FAB() }) { }","Column { TopAppBar(); Content(); Box { FAB() } }",High,https://developer.android.com/develop/ui/compose/components/scaffold
35,Layouts,Use WindowSizeClass for adaptive layouts,WindowSizeClass enables responsive design,Check window size for layout decisions,Use fixed layouts for all screen sizes,"when (windowSizeClass.widthSizeClass) { Compact -> Phone(); Expanded -> Tablet() }",Same layout for phone and tablet,Critical,https://developer.android.com/develop/ui/compose/layouts/adaptive
36,Layouts,Support foldable devices,Use WindowInfoTracker for fold awareness,Adapt layout for fold position,Ignore foldable device states,"val foldingFeatures = windowInfoTracker.windowLayoutInfo.collectAsState()",Fixed layout ignoring fold,Medium,https://developer.android.com/develop/ui/compose/layouts/adaptive/foldables
37,Layouts,Use Modifier.weight for flexible sizing,weight distributes space proportionally in Row/Column,Use weight for flexible space distribution,Use fixed sizes for flexible content,"Row { Text(Modifier.weight(1f)); Button() }","Row { Text(Modifier.width(200.dp)); Button() }",Medium,https://developer.android.com/develop/ui/compose/modifiers#weight
38,Layouts,Use FlowRow and FlowColumn for wrapping,Flow layouts wrap content to next line,Use for tags and chips that wrap,Force single line or manual wrapping,"FlowRow { tags.forEach { Chip(it) } }","Row(Modifier.horizontalScroll()) { tags.forEach { Chip(it) } }",Medium,https://developer.android.com/develop/ui/compose/layouts/flow
39,Components,Use Material 3 components,Material 3 provides modern design components,Use M3 components from material3 package,Mix M2 and M3 components,"import androidx.compose.material3.Button","import androidx.compose.material.Button in M3 app",High,https://developer.android.com/develop/ui/compose/designsystems/material3
40,Components,Use Button variants appropriately,Different button types for different emphasis,Use FilledButton for primary actions,Use same button style for all actions,"Button { } // Primary; OutlinedButton { } // Secondary; TextButton { } // Tertiary",Button for all actions,Medium,https://developer.android.com/develop/ui/compose/components/button
41,Components,Use Card for contained content,Card groups related content with elevation,Use Card for distinct content groups,Use Box with border for card-like UI,"Card { Column { Title(); Content() } }","Box(Modifier.border(1.dp, Color.Gray)) { }",Medium,https://developer.android.com/develop/ui/compose/components/card
42,Components,Use AlertDialog for confirmations,AlertDialog presents important choices,Use for destructive action confirmations,Use for non-critical information,"AlertDialog(onDismissRequest = {}, confirmButton = {}, title = {})","Box(Modifier.background(Color.White)) { custom dialog }",High,https://developer.android.com/develop/ui/compose/components/dialog
43,Components,Use TopAppBar correctly,TopAppBar provides navigation and actions,Use CenterAlignedTopAppBar or MediumTopAppBar,Build custom app bar with Row,"TopAppBar(title = { Text(""Title"") }, navigationIcon = { IconButton { } })","Row { IconButton { }; Text(""Title"") }",High,https://developer.android.com/develop/ui/compose/components/app-bars
44,Components,Use NavigationBar for bottom nav,NavigationBar provides M3 bottom navigation,Use for 3-5 top-level destinations,Use for more than 5 destinations,"NavigationBar { NavigationBarItem(selected, onClick, icon, label) }","Row { destinations.forEach { BottomNavItem() } }",High,https://developer.android.com/develop/ui/compose/components/bottom-nav-bar
45,Components,Use TextField with proper state,TextField needs controlled state management,Hoist TextField state properly,"Keep state internal without callback","TextField(value = text, onValueChange = { text = it })","TextField(value = text, onValueChange = { }) // No state update",Critical,https://developer.android.com/develop/ui/compose/text/user-input
46,Components,Use OutlinedTextField for forms,OutlinedTextField provides clear input boundaries,Use OutlinedTextField in forms,Use TextField without visual boundaries in forms,"OutlinedTextField(value, onValueChange, label = { Text(""Email"") })",TextField without label in form,Medium,https://developer.android.com/develop/ui/compose/text/user-input
47,Components,Use Checkbox with label,Checkbox should have associated clickable label,Make entire row clickable for checkbox,"Only make checkbox itself clickable","Row(Modifier.clickable { checked = !checked }) { Checkbox(checked, null); Text(""Label"") }","Row { Checkbox(checked, { checked = it }); Text(""Label"") }",High,https://developer.android.com/develop/ui/compose/components/checkbox
48,Components,Use Switch for on/off settings,Switch represents binary on/off state,Use Switch for immediate effect toggles,Use Switch for form submissions,"Switch(checked = enabled, onCheckedChange = { enabled = it })","Checkbox for on/off settings",Medium,https://developer.android.com/develop/ui/compose/components/switch
49,Components,Use FloatingActionButton correctly,FAB is for primary screen action,Use single FAB per screen for main action,Use multiple FABs on same screen,"FloatingActionButton(onClick = { addItem() }) { Icon(Icons.Default.Add) }","Multiple FABs stacked vertically",High,https://developer.android.com/develop/ui/compose/components/fab
50,Components,Use Chip for selections and filters,Chips are compact elements for input or filtering,Use FilterChip for multi-select filters,Use Button where Chip is appropriate,"FilterChip(selected, onClick, label = { Text(""Filter"") })","Button(Modifier.height(32.dp)) { Text(""Filter"") }",Medium,https://developer.android.com/develop/ui/compose/components/chip
51,Components,Use NavigationRail for tablets,NavigationRail provides side navigation for larger screens,Use NavigationRail on expanded width,Use bottom nav on tablet landscape,"NavigationRail { NavigationRailItem() }",NavigationBar on tablet,High,https://developer.android.com/develop/ui/compose/components/navigation-rail
52,Components,Use SnackBar for brief messages,Snackbar shows brief feedback messages,Use Scaffold's snackbarHost for Snackbars,Show Snackbar without SnackbarHost,"Scaffold(snackbarHost = { SnackbarHost(snackbarHostState) })",Toast.makeText in Compose,Medium,https://developer.android.com/develop/ui/compose/components/snackbar
53,Components,Use DropdownMenu for overflow actions,DropdownMenu shows contextual actions,Use for secondary actions overflow,Use Dialog for simple action selection,"DropdownMenu(expanded, onDismissRequest) { DropdownMenuItem() }","AlertDialog with list of actions",Medium,https://developer.android.com/develop/ui/compose/components/menu
54,Performance,Minimize recompositions,Recomposition should only update changed parts,Use stable parameters and remember,Pass unstable lambdas and objects,onClick = remember { { viewModel.click() } },"onClick = { viewModel.click() } // Recreated each recomposition",High,https://developer.android.com/develop/ui/compose/performance/stability
55,Performance,Use @Stable and @Immutable,Annotations help Compose skip recomposition,Mark stable classes appropriately,Assume Compose infers stability correctly,@Stable class UiState(val items: List<Item>),class UiState(val items: List<Item>) // Not marked,Medium,https://developer.android.com/develop/ui/compose/performance/stability#stable-types
56,Performance,Use key() for item identity,key() helps Compose identify items in loops,Provide key for items in forEach,"Rely on positional identity in loops","items.forEach { key(it.id) { ItemCard(it) } }","items.forEach { ItemCard(it) }",High,https://developer.android.com/develop/ui/compose/lists#item-keys
57,Performance,Defer reads when possible,Defer state reads to limit recomposition scope,Use lambda for frequently changing values,Read state at high level and pass down,"Modifier.offset { IntOffset(scrollState.value, 0) }","Modifier.offset(x = scrollState.value.dp)",High,https://developer.android.com/develop/ui/compose/performance/bestpractices#defer-reads
58,Performance,Use Layout Inspector for debugging,Layout Inspector shows recomposition counts,Profile recomposition to find issues,Guess at performance problems,"Android Studio > Tools > Layout Inspector",Print statements for recomposition tracking,Medium,https://developer.android.com/studio/debug/layout-inspector
59,Performance,Avoid expensive operations in composition,Composition runs frequently and should be fast,Move computation to ViewModel or remember,Calculate in composable body,val sorted = remember(list) { list.sortedBy { it.name } },val sorted = list.sortedBy { it.name },Critical,https://developer.android.com/develop/ui/compose/performance/bestpractices
60,Accessibility,Provide contentDescription for images,Screen readers need image descriptions,Add meaningful contentDescription,Leave contentDescription null for meaningful images,"Icon(imageVector, contentDescription = ""Add item"")","Icon(imageVector, contentDescription = null) // For meaningful icon",Critical,https://developer.android.com/develop/ui/compose/accessibility
61,Accessibility,Use semantic properties,Semantics provide accessibility information,Add semantics for custom components,Ignore semantics for interactive elements,"Modifier.semantics { role = Role.Button; contentDescription = ""Submit"" }",Custom button without semantics,High,https://developer.android.com/develop/ui/compose/accessibility/semantics
62,Accessibility,Support content scaling,Users may increase font size,Use sp for text and support dynamic sizing,Use fixed dp for text sizes,"Text(""Hello"", fontSize = 16.sp)",Text(fontSize = 16.dp) // Not accessible,High,https://developer.android.com/develop/ui/compose/accessibility
63,Accessibility,Ensure touch target size,Minimum touch target is 48dp,Ensure clickable areas are at least 48dp,Make touch targets too small,"IconButton(onClick = {}, Modifier.size(48.dp)) { Icon() }","Icon(Modifier.size(24.dp).clickable { }) // Too small",High,https://developer.android.com/develop/ui/compose/accessibility
64,Accessibility,Handle focus properly,Focus navigation should be logical,Manage focus order and traversal,Ignore focus for keyboard/TalkBack users,"Modifier.focusable(); FocusRequester",No focus management,Medium,https://developer.android.com/develop/ui/compose/accessibility#focus
65,Accessibility,Use clearAndSetSemantics for grouping,Merge semantics for grouped content,Group related content for screen readers,Leave each element with separate semantics,"Row(Modifier.clearAndSetSemantics { contentDescription = ""5 stars"" }) { Stars() }",Each star with separate description,Medium,https://developer.android.com/develop/ui/compose/accessibility/semantics
66,Testing,Use Compose testing APIs,Compose provides dedicated testing utilities,Use ComposeTestRule for UI tests,Use Espresso directly with Compose,"composeTestRule.onNodeWithText(""Login"").performClick()","onView(withText(""Login"")).perform(click())",High,https://developer.android.com/develop/ui/compose/testing
67,Testing,Use semantic matchers,Find nodes by semantics for reliable tests,Use onNodeWithContentDescription and semantic matchers,Find by internal implementation details,"onNodeWithContentDescription(""Add item"").performClick()","onNode(hasTestTag(""btn_add_internal"")).performClick()",Medium,https://developer.android.com/develop/ui/compose/testing#finders
68,Testing,Use testTag for complex cases,testTag helps find specific nodes,Use testTag when semantics are insufficient,Overuse testTag instead of semantics,"Modifier.testTag(""user_list""); onNodeWithTag(""user_list"")","testTag on every composable",Medium,https://developer.android.com/develop/ui/compose/testing#tags
69,Testing,Test state changes,Verify UI updates with state changes,Assert UI reflects state changes,"Only test initial state","rule.onNodeWithText(""0"").assertExists(); increment(); rule.onNodeWithText(""1"").assertExists()",Test only initial render,High,https://developer.android.com/develop/ui/compose/testing
70,Testing,Use createComposeRule for unit tests,createComposeRule provides isolated Compose testing,Use for testing individual composables,Use createAndroidComposeRule for unit tests,"@get:Rule val rule = createComposeRule(); rule.setContent { MyComposable() }",createAndroidComposeRule for simple composable tests,Medium,https://developer.android.com/develop/ui/compose/testing#setup