← All courses

Jetpack Compose Interview Questions & Answers

🗓 May 31, 2026 ⏱ 10 min read

A complete bank of Jetpack Compose interview questions, from fundamentals to advanced internals. Each answer is point-by-point for clear delivery.

1. What is Jetpack Compose?

  • Android’s modern declarative UI toolkit written in Kotlin.
  • You describe UI for the current state; it updates automatically.
  • No XML or findViewById.

2. Declarative vs imperative UI.

  • Imperative (Views) — find a view and mutate it.
  • Declarative (Compose) — describe the result; the framework computes changes.

3. What is a @Composable function?

  • A function annotated @Composable that emits UI.
  • Can call other composables; should be side-effect free and idempotent.

4. What is recomposition?

  • Re-running composables that read changed state.
  • It is smart/partial — only readers recompose.
  • Can run often and in any order.

5. What are the three phases of Compose?

  • Composition — what to show.
  • Layout — measure and place.
  • Drawing — render to the canvas.

6. What is mutableStateOf?

  • Creates observable state; reading it subscribes the composable.
  • Changing it triggers recomposition of readers.

7. What does remember do?

  • Keeps a value across recompositions.
  • Without it, the value resets every recomposition.

8. remember vs rememberSaveable.

  • remember — survives recomposition only.
  • rememberSaveable — also survives configuration change/process death (saved to a Bundle).

9. What is the by keyword with state?

  • A property delegate so you read/write count directly instead of count.value.
  • Requires import androidx.compose.runtime.getValue/setValue.

10. What is state hoisting?

  • Move state to the caller; pass value down, events up.
  • Makes composables stateless, reusable and testable.

11. Explain Unidirectional Data Flow (UDF).

  • State flows down, events flow up to the owner.
  • Predictable, easy to debug and test.

12. Stateful vs stateless composable.

  • Stateful — owns its state.
  • Stateless — receives state + event callbacks; preferred for reuse.

13. What is derivedStateOf and when to use it?

  • Computes a value from other state; recomposes only when the result changes.
  • Use to avoid excessive recomposition (e.g. show button when index > 0).

14. What is a Modifier?

  • Decorates a composable: size, padding, background, click, etc.
  • Chainable; pass a modifier param into reusable composables.

15. Why does Modifier order matter?

  • Each modifier wraps the previous, so order changes the result.
  • e.g. padding().background() differs from background().padding().

16. Column, Row and Box.

  • Column — vertical, Row — horizontal, Box — layered.
  • Control spacing with Arrangement, alignment with Alignment.

17. How do you share space between children?

  • Use Modifier.weight() inside Row/Column.
  • Use Spacer for fixed or flexible gaps.

18. How are lists rendered efficiently?

  • LazyColumn/LazyRow compose only visible items, recycling them.
  • Always pass a stable key.

19. Why pass a key in LazyColumn items?

  • Stable identity for correct recycling, animation and state preservation.
  • Without it, updates can be wrong or janky.

20. What is contentType in lazy lists?

  • Hints the type of each item so Compose reuses compatible compositions.
  • Improves performance in heterogeneous lists.

21. How do you make a grid?

  • LazyVerticalGrid with GridCells.Fixed(n) or GridCells.Adaptive(size).

22. Why must composables be side-effect free?

  • They recompose unpredictably; side effects in the body would run many times.
  • Use effect APIs to run them safely.

23. What is LaunchedEffect?

  • Runs a coroutine when the composable enters composition, restarting when keys change.
  • Use for loading data for an id.

24. What is rememberCoroutineScope?

  • A scope to launch coroutines from a callback (e.g. a button tap).
  • Tied to the composition’s lifetime.

25. What is DisposableEffect?

  • Set up something and clean it up via onDispose (e.g. register/unregister a listener).

26. SideEffect vs LaunchedEffect.

  • SideEffect — runs after every successful recomposition (publish state to non-Compose code).
  • LaunchedEffect — runs a coroutine tied to keys.

27. What is rememberUpdatedState?

  • Captures the latest value inside a long-running effect without restarting it.

28. What is produceState?

  • Converts non-Compose async sources into Compose State.

29. What is snapshotFlow?

  • Converts Compose State reads into a Flow you can collect (e.g. observe scroll position).

30. How do you connect Compose to a ViewModel?

  • Expose a read-only StateFlow of UI state.
  • Collect with collectAsStateWithLifecycle().
  • Render with a when.

31. collectAsState vs collectAsStateWithLifecycle.

  • collectAsState — collects regardless of lifecycle.
  • collectAsStateWithLifecycle — pauses when the screen isn’t visible (preferred).

32. What is CompositionLocal?

  • Implicitly passes data down the tree without threading it through every parameter.
  • Examples: LocalContext, LocalDensity; use sparingly.

33. What is the slot API pattern?

  • Composables accept other composables (content: @Composable () -> Unit).
  • Enables flexible, reusable components (e.g. Scaffold, Card).

34. What is Scaffold?

  • A screen skeleton with slots: top bar, bottom bar, FAB, content.
  • Apply its innerPadding to avoid overlap.

35. How does theming work?

  • MaterialTheme provides colorScheme, typography, shapes.
  • Read via MaterialTheme.colorScheme; use isSystemInDarkTheme().

36. How do you do navigation in Compose?

  • NavHost + NavController; composable("route") destinations.
  • Pass typed arguments; hoist navigation events out of deep composables.

37. What is the simplest animation API?

  • animate*AsState (e.g. animateColorAsState, animateDpAsState).
  • Change the target value and it animates automatically.

38. AnimatedVisibility vs animateContentSize.

  • AnimatedVisibility — animates a composable appearing/disappearing.
  • animateContentSize — animates size changes of content.

39. updateTransition and Animatable.

  • updateTransition — coordinate multiple animated values together.
  • Animatable — imperative control for gesture/looping animations.

40. What makes a composable skippable?

  • If its parameters are stable and unchanged, Compose can skip recomposing it.
  • Unstable params force recomposition.

41. What are @Stable and @Immutable?

  • Annotations telling Compose a type’s instances won’t change in ways that affect composition.
  • Helps the compiler mark composables skippable.

42. Why can a lambda cause extra recomposition, and how to fix it?

  • A new lambda each recomposition is an unstable parameter.
  • Use remember or method references to keep it stable.

43. What is the key() composable for?

  • Gives a composable a stable identity so its state is preserved/distinguished in loops.

44. What are remember keys?

  • remember(key1, key2) { } recomputes when a key changes.
  • Use to recompute derived values when inputs change.

45. How do you handle a TextField (controlled input)?

  • Hold the text in state; pass value and onValueChange.
  • This two-way pattern keeps state and UI in sync.

46. What is the @Preview annotation?

  • Renders a composable live in Android Studio without running the app.
  • Supports dark mode, font scale, device variants; wrap in your theme.

47. How does Compose interoperate with Views?

  • Host Compose in Views via ComposeView; host Views in Compose via AndroidView.
  • Enables gradual migration.

48. How do you test Compose UI?

  • Use createComposeRule() and semantics matchers (onNodeWithText, performClick).
  • Assert with assertIsDisplayed() etc.

49. What is the semantics tree?

  • A parallel tree describing UI meaning for accessibility and testing.
  • Add Modifier.semantics { } or contentDescription for a11y.

50. How do you make Compose accessible?

  • Provide contentDescription for images/icons, mergeDescendants where appropriate, and adequate touch targets.

51. What is BoxWithConstraints?

  • A Box that exposes the incoming constraints (maxWidth/maxHeight) so you can adapt layout responsively.

52. How do custom layouts work (Layout composable)?

  • Use the Layout composable: measure children with constraints, then place them.
  • For full control beyond Row/Column/Box.

53. What is SubcomposeLayout?

  • Lets you compose content during the measure phase (e.g. size one part based on another).
  • Used by components like LazyColumn.

54. What are intrinsic measurements?

  • Query a child’s natural size (min/max width/height) to size siblings (e.g. equal-height items).

55. How do you handle gestures?

  • Modifier.clickable, pointerInput with detectors (detectTapGestures, detectDragGestures), draggable, swipeable.

56. How do you draw custom graphics?

  • Use Canvas / Modifier.drawBehind / drawWithContent with the DrawScope API.

57. What is graphicsLayer used for?

  • Applies transformations (scale, rotate, alpha, clip) efficiently on a separate layer.
  • Good for animations without triggering layout.

58. What is a recomposition scope?

  • The smallest region Compose can recompose independently.
  • Reading state in a small child limits recomposition to that child.

59. How do you minimise recomposition?

  • Read state as low as possible, use stable params, defer reads (lambda-based modifiers), and use derivedStateOf.

60. What is deferred state read / lambda modifier?

  • Passing a lambda (e.g. Modifier.offset { }) reads state in the layout/draw phase, skipping recomposition.
  • A key performance technique for animations/scroll.

61. Why are immutable data classes recommended for state?

  • They’re stable/skippable and make recomposition predictable.
  • Mutable shared objects can confuse Compose’s change tracking.

62. What is the difference between Compose state and a regular variable?

  • A plain var isn’t observed — changing it won’t recompose.
  • Use mutableStateOf so Compose tracks reads/writes.

63. How do you preserve scroll position?

  • Use rememberLazyListState() (it’s saveable) and pass it to the list.

64. How do you implement pull-to-refresh?

  • Use the Material pull-to-refresh component/state with a refreshing flag from the ViewModel.

65. How do you show a Snackbar?

  • Use a SnackbarHostState + rememberCoroutineScope to call showSnackbar from an event.

66. How do you show dialogs?

  • Conditionally render AlertDialog/Dialog based on state; dismiss by flipping the state.

67. How does Compose handle configuration changes?

  • State in rememberSaveable or the ViewModel survives; transient remember state does not.

68. What is the role of the Compose compiler plugin?

  • Transforms composable functions, tracks state reads, and enables skipping/positional memoization.

69. What is positional memoization?

  • Compose identifies composables by their position in the tree to remember their state across recompositions.

70. What is the difference between Modifier.padding and Spacer?

  • padding — space around a single composable.
  • Spacer — an empty composable creating gap between siblings.

71. How do you handle focus and keyboard?

  • Use FocusRequester, Modifier.focusRequester, keyboard options/actions on TextField, and IME insets.

72. How do you handle window insets (status bar, IME)?

  • Use the insets APIs (Modifier.windowInsetsPadding, imePadding) for edge-to-edge layouts.

73. How do you load images in Compose?

  • Use Coil’s AsyncImage; it caches and downsamples off the main thread.

74. What is LazyListState used for besides scroll position?

  • Programmatic scrolling (animateScrollToItem) and observing visible items for paging/analytics.

75. How do sticky headers work?

  • stickyHeader { } inside a LazyColumn keeps a header pinned while its section scrolls.

76. How do you paginate in Compose?

  • Use Paging 3 with collectAsLazyPagingItems() and render loading/append states.

77. What is the difference between Compose Material and Material3?

  • Material3 implements the newer Material You design (dynamic color, updated components).
  • Use Material3 for new apps.

78. What is dynamic color?

  • On Android 12+, derive the color scheme from the user’s wallpaper via dynamicColorScheme.

79. How do you provide custom design tokens?

  • Define your own values and pass them via a custom CompositionLocalProvider or extend the theme.

80. What is the difference between Composable content and a normal function returning a View?

  • Composables emit UI into the composition; they don’t return a View object.
  • Compose manages their lifecycle and recomposition.

81. How do you avoid running a network call on every recomposition?

  • Never call it in the body; use LaunchedEffect with a stable key, or trigger it from the ViewModel.

82. What is remember with a calculation vs rememberSaveable limits?

  • rememberSaveable can only store types that fit in a Bundle (or with a custom Saver).

83. What is a Saver?

  • Tells rememberSaveable how to convert a custom type to/from a saveable representation.

84. How do you handle one-time events (navigation, toasts) with state?

  • Use a SharedFlow/Channel for events (not StateFlow), or a consumed event wrapper, collected in a LaunchedEffect.

85. What is the difference between Modifier.then and chaining?

  • then concatenates two modifiers; chaining (.padding().background()) is the common form built on it.

86. How do you reuse styling across composables?

  • Extract a custom composable, or pass a shared Modifier, or define an extension on Modifier.

87. Why is Compose good for design systems?

  • Components are just functions — easy to compose, theme and test consistently.

88. Is Compose production-ready and what are its trade-offs?

  • Yes — stable and recommended for new Android UI.
  • Trade-offs: a learning curve (recomposition model) and some maturity gaps vs the long-standing View system, mostly closed.
Interview tip: if you can clearly explain recomposition, state & stability/skippability, and side-effect APIs, you’ll handle almost any Compose follow-up — these are the senior-level differentiators.