Jetpack Compose Interview Questions & Answers
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
@Composablethat 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
countdirectly instead ofcount.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
modifierparam into reusable composables.
15. Why does Modifier order matter?
- Each modifier wraps the previous, so order changes the result.
- e.g.
padding().background()differs frombackground().padding().
16. Column, Row and Box.
- Column — vertical, Row — horizontal, Box — layered.
- Control spacing with
Arrangement, alignment withAlignment.
17. How do you share space between children?
- Use
Modifier.weight()inside Row/Column. - Use
Spacerfor fixed or flexible gaps.
18. How are lists rendered efficiently?
LazyColumn/LazyRowcompose 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?
LazyVerticalGridwithGridCells.Fixed(n)orGridCells.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
Statereads into a Flow you can collect (e.g. observe scroll position).
30. How do you connect Compose to a ViewModel?
- Expose a read-only
StateFlowof 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
innerPaddingto avoid overlap.
35. How does theming work?
MaterialThemeprovides colorScheme, typography, shapes.- Read via
MaterialTheme.colorScheme; useisSystemInDarkTheme().
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
rememberor 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
valueandonValueChange. - 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 viaAndroidView. - 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 { }orcontentDescriptionfor a11y.
50. How do you make Compose accessible?
- Provide
contentDescriptionfor 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
Layoutcomposable: 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,pointerInputwith detectors (detectTapGestures,detectDragGestures),draggable,swipeable.
56. How do you draw custom graphics?
- Use
Canvas/Modifier.drawBehind/drawWithContentwith 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
varisn’t observed — changing it won’t recompose. - Use
mutableStateOfso 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+rememberCoroutineScopeto callshowSnackbarfrom an event.
66. How do you show dialogs?
- Conditionally render
AlertDialog/Dialogbased on state; dismiss by flipping the state.
67. How does Compose handle configuration changes?
- State in
rememberSaveableor the ViewModel survives; transientrememberstate 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
CompositionLocalProvideror 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
LaunchedEffectwith a stable key, or trigger it from the ViewModel.
82. What is remember with a calculation vs rememberSaveable limits?
rememberSaveablecan only store types that fit in a Bundle (or with a custom Saver).
83. What is a Saver?
- Tells
rememberSaveablehow 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?
thenconcatenates 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 onModifier.
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.