On Nov 4, 2026 the Android team published its Android Developer Summit Compose round-up. Most of the headline items are previews of things already in flight: the upcoming Compose 1.13 stable, Jetpack AppState in alpha, and Navigation 3 1.2 deep links. The part I think is underrated is smaller: a new Compose performance entry in the official Android skills repo, last updated 2026-10-22. It is written for coding agents, but it is also the most compact statement of Google's current Compose performance advice I have seen, and it reads well as a human code-review checklist.
Scope note: the blog post links to Summit session videos and does not publish API signatures or artifact versions for Compose 1.13. I only state what the post and the skill file say, and I have not invented version numbers.
What the round-up announced
- Compose 1.13 (upcoming stable): built-in adaptive layout support through Grid and FlexBox, plus Progressive Blur and Formatted Text. I covered the pre-release APIs in the 1.13 alpha01 and beta posts.
- Text editing: a rewritten
BasicTextFieldwith a buffer-driven architecture andTextFieldState, which the post says removes IME race conditions and supports rich-text formatted editing. - Jetpack AppState (alpha):
Transformderives reactive state from State and Flow inputs, andStateStoreis a keyed container shared across activities, services, widgets and App Functions, with optional DataStore persistence. See my AppState deep dive. - Navigation 3 1.2: type-safe deep linking with Kotlin Serialization, custom argument parsing, and lazily built synthetic back stacks.
- Input: the layered input system extends to trackpads, mice and physical controls, relevant to Googlebook and large screens.
The four Compose skills
The post lists what currently exists in the Android skills repo for Compose: an updated Adaptive skill (now adds foldable and desktop support, handling windowing, keyboard shortcuts, tooltips and trackpad hover states), a new Compose performance skill, an XML to Compose migration skill, and a new Ink skill. If skills are new to you, my Android Skills post explains the model.
The performance skill, read as a checklist
The skill starts with prerequisites that no amount of code review can replace: profile release builds only (debuggable builds degrade ART performance), keep R8 minification on, and generate baseline profiles for critical journeys such as cold start and key scrolling feeds. Then it audits seven categories. These are the rules I would put in a PR template.
1. State: defer reads, derive cheaply
Defer state reads to the layout or draw phase by passing lambdas, so a fast-changing value does not recompose its parent. The skill also says to prefer computedStateOf on Compose 1.13+ for fast-changing simple conditions, and derivedStateOf for heavier calculations.
// Reads scroll offset during composition: recomposes on every frame
@Composable
fun Header(scroll: ScrollState) {
val alpha = 1f - (scroll.value / 300f).coerceIn(0f, 1f)
Box(Modifier.alpha(alpha)) { /* ... */ }
}
// Reads it in the draw phase: no recomposition
@Composable
fun Header(scroll: ScrollState) {
Box(
Modifier.graphicsLayer {
alpha = 1f - (scroll.value / 300f).coerceIn(0f, 1f)
}
) { /* ... */ }
}
On stability, the guidance is deliberately restrained: Strong Skipping Mode already handles most cases, so do not sprinkle @Stable, @Immutable or ImmutableList over collection models. Focus on making composables cheap rather than maximizing skips.
2. Layouts and measurement
Avoid onGloballyPositioned; use onVisibilityChanged, onPlaced, onLayoutRectChanged or requireLayoutCoordinates(). Anchor floating content with a custom Layout rather than coordinates stored in state, use the lambda form of Modifier.offset, and keep BoxWithConstraints and SubcomposeLayout out of hot paths.
3. Lazy layouts
Always provide primitive key and contentType, replace indexOf lookups with itemsIndexed, use a Set for selection state, resolve CompositionLocals in the parent, and collect shared flows once in the parent instead of per item. Do not fire analytics from pre-fetched items; use visibility-based tracking.
LazyColumn {
itemsIndexed(
items = messages,
key = { _, m -> m.id },
contentType = { _, m -> m.kind }
) { index, message ->
MessageRow(
message = message,
selected = message.id in selectedIds,
onClick = { onSelect(message.id) }
)
}
}
4. Animation and shared transitions
Read animated alpha, scale, rotation and color inside graphicsLayer; use offset {}, layout {} or animateBounds for position and size; attach shared transitions only when the item is visible.
5. Effects and threading
No side effects in the composable body. Do not use LaunchedEffect for synchronous work, and do not leave an empty onDispose in a DisposableEffect. Use collectAsStateWithLifecycle() for UI flows, rememberUpdatedState for stale captures, and replace Handler.postDelayed or TimerTask with LaunchedEffect plus delay().
6. Graphics and custom drawing
Replace decorative Canvas nodes with drawWithCache so paths, paints and brushes are built once. Remember RuntimeShader and ShaderBrush, prefer Path.rewind() over reset() in hot loops, and avoid Pair, Triple and HashSet<Long> in drawing code in favor of MutableLongSet.
fun Modifier.badgeBackground(color: Color) = this.drawWithCache {
val path = Path().apply {
addRoundRect(RoundRect(size.toRect(), CornerRadius(12.dp.toPx())))
}
onDrawBehind { drawPath(path, color) }
}
7. Custom modifiers
Migrate legacy Modifier.composed to ModifierNodeElement plus Modifier.Node (or DelegatingNode when delegating), using capability interfaces such as DrawModifierNode and LayoutModifierNode. Query requireLayoutCoordinates() on demand instead of implementing GlobalPositionAwareModifierNode.
private data class CircleElement(val color: Color) : ModifierNodeElement<CircleNode>() {
override fun create() = CircleNode(color)
override fun update(node: CircleNode) { node.color = color }
}
private class CircleNode(var color: Color) : Modifier.Node(), DrawModifierNode {
override fun ContentDrawScope.draw() {
drawCircle(color)
drawContent()
}
}
fun Modifier.circle(color: Color) = this then CircleElement(color)
The sample code above follows the patterns the skill describes; the skill file itself only paraphrases the modifier example, so treat my snippets as illustrations and check them against your Compose version.
Why it matters beyond agents
Two things stand out. First, the skill tells an agent to read a per-category reference file before flagging or editing anything, which is exactly how a good reviewer should work: know the approved fix and its scope limits before commenting. Second, the guidance is notably anti-cargo-cult. No blanket stability annotations, no wrapping everything in remember, and a plain getter for trivial values. If you inherited a codebase full of defensive annotations, that is a useful permission slip to simplify.
What I would do this week
- Turn the seven categories into a short PR checklist and run it against your two hottest screens.
- Grep for
onGloballyPositioned,Modifier.composed,Handler.postDelayedand lazy items without akey. - Confirm your benchmark runs use a release build with R8 and a baseline profile.
- If you use coding agents, install the Android skills through the Android CLI and compare the agent's findings with your own review.
- Read the Summit sessions on Compose performance and recomposition tracing with Perfetto before you pick what to optimize.
Sources: the Android Developers Blog post "Build for every screen with the latest Jetpack Compose updates from Android Developer Summit" (Nov 4, 2026) and the jetpack-compose-performance SKILL.md in the android/skills repository, both retrieved Nov 8, 2026.
No comments yet. Be the first to leave one!