Contents — page 4 of 4
Day 76Focus is the input model you don't test until someone plugs in a keyboardCompose's focus system handles keyboard, D-pad and accessibility navigation. The APIs are small, but modifier order matters, and a form with no focus handling is unusable on any device without a touchscreen.Day 77Drag-and-drop crosses app boundaries, which is why it isn't just a drag gestureCompose's drag-and-drop moves ClipData between sources and targets, including across apps. Reordering a list is a different problem with a different solution, and conflating them is why reorder implementations get complicated.Day 78Compose performance is one question asked in four placesCompose performance work reduces to knowing which of composition, layout and draw is being invalidated, and why. The diagnostic order matters more than any individual optimisation.Day 79The compiler decides your types are unstable, and it writes down whyCompose infers stability per class and per parameter, and can emit a report saying what it concluded. Understanding the inference rules — and why List is unstable — explains most unnecessary recomposition.Day 80Strong skipping made most of yesterday's advice unnecessaryStrong skipping lets composables skip even with unstable parameters, using instance comparison, and memoises lambdas automatically. It removes most of the need for @Immutable annotations and changes what the compiler report means.Day 81Baseline Profiles fix a problem recomposition counts can't seeBaseline Profiles ship a list of hot methods so ART compiles them at install time instead of interpreting them on first run. They typically cut startup and first-scroll jank by 20-30% and are unrelated to Compose recomposition.Day 82Nine pillars have quietly been teaching you one optimisationReading a state value later — in a lambda rather than as a parameter — moves the invalidation from composition to layout or draw. It is the single highest-leverage Compose optimisation, and it has one shape.Day 83Four tools, four questions, and none of them answers another'sLayout Inspector, the compiler reports, Macrobenchmark and the system trace each answer a different question. Using the wrong one produces confident, wrong conclusions, and knowing the split is most of performance work.Day 84Your UI tests query the accessibility tree, which is why testTag is a last resortCompose UI tests match against the semantics tree, not the layout. Selecting by text and content description tests what users perceive; selecting by testTag tests an implementation detail you invented for the test.Day 85Find, act, assert — and the rule that decides which test to write at allCompose testing is finders, actions and assertions over the semantics tree. The API is small; the judgment is choosing between a unit test, a Compose test with a fake, and a full instrumented test.Day 86A flaky test is a timing assumption you didn't know you madeCompose's test framework auto-syncs with the composition, so most tests need no waiting at all. The failures come from things that never go idle, and from work the framework cannot see.Day 87What a Compose test suite should actually containA useful Compose suite is mostly unit tests, a layer of state-driven component tests, screenshot tests for visual regressions, and a handful of journeys. The shape matters more than the count.Day 88ComposeView is easy; deciding where to put it is the migrationAdding Compose to a View-based app is one class. The interesting decisions are which seam to cut at, and the ViewCompositionStrategy that governs when the composition is disposed.Day 89AndroidView has two lambdas, and putting work in the wrong one is the bugAndroidView embeds a View inside Compose. Its factory lambda constructs, its update lambda binds, and conflating them causes either a View recreated per frame or one that never reflects new state.Day 90Porting a RecyclerView deletes four classes and keeps one ideaA RecyclerView migration removes most of its own machinery, because Compose's composition already does recycling and diffing. What survives is stable identity — getItemId becomes key — and knowing that makes the port mechanical.Day 91Two navigation systems can share one back stack, which is the only reason this worksNavigation Compose and the fragment navigator can coexist in one NavHost via the fragment interop artifact. That shared back stack is what makes an incremental screen-by-screen migration possible.Day 92A preview that needs a ViewModel is telling you something@Preview renders a composable without running the app. Its real value is the pressure it applies: a component that can't be previewed is a component that can't be tested, and both point at the same design problem.Day 93The Layout Inspector shows you a tree you didn't writeLayout Inspector renders the composition as an inspectable tree with per-composable recomposition and skip counts. Knowing what it can and cannot tell you is the difference between a diagnosis and a guess.Day 94The checks that run without you asking are the ones that scaleCompose ships lint rules for the modifier convention, remember misuse, unstable collections and more. Adding your own is how a design-system convention becomes a build failure instead of a code-review comment.Day 95Edge-to-edge stopped being a choice, and most apps found out from a bug reportTargeting Android 15 makes edge-to-edge mandatory — the opt-out is gone. What that changes, what breaks, and why the fix is mostly about who consumes the insets.Day 96There are three kinds of inset, and using the wrong one is why your keyboard fights your layoutCompose exposes system insets as composable values with padding, size and consume modifiers. Knowing the three safe-inset groups and how the keyboard inset animates resolves most edge-to-edge layout problems.Day 97Predictive back turns a commitment into a preview, and your BackHandler can break itPredictive back shows a preview of the destination during the gesture. Supporting it means responding to progress rather than to a completed press, and the old BackHandler cannot express that.Day 98Notifications are the one UI you can't build in ComposeA notification is rendered by the system UI, not your app, so Compose plays no part in its appearance. What a Compose app owns is the permission flow, the deep link, and the back stack the user lands in.Day 99Glance looks like Compose and compiles to RemoteViews, which explains every limitationGlance lets you write widgets in Compose-like Kotlin, but it emits RemoteViews rather than drawing. Knowing that explains the missing modifiers, the absent animations, and why state works the way it does.Day 100100 days of Compose: the eight ideas the other ninety-nine posts kept circlingA hundred days of Jetpack Compose, written by following the official documentation end to end. The APIs are many and the ideas are few; here are the eight that kept recurring, and an honest account of what the exercise missed.