跪拜 Guibai
← All articles
Kotlin · Android

Compose 1.12 Lands Mesh Gradients, WCG, and a SideEffect That's 90% Faster Than LaunchedEffect

By RockByte ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

The Styles API's binary-incompatible changes mean any project mixing old and new Compose libraries can crash at runtime even with a clean build — a dependency hygiene trap that hits multi-module Android apps hard. The keyed SideEffect and test-sync APIs address two long-standing pain points: coroutine overhead for simple effects and flaky animation tests.

Summary

Compose 1.12 raises compileSdk to API 37 and requires AGP 9.1.1, deprecating Modifier.onFirstVisible() in favor of onVisibilityChanged(). The experimental Styles API carries binary-incompatible changes to functions like size, so libraries built against older Compose versions can crash at runtime even if the consuming project compiles cleanly.

A new keyed SideEffect overload handles one-shot side effects without coroutine overhead, clocking up to 90% faster than LaunchedEffect. MeshGradientPainter produces multi-control-point gradients, while the graphics pipeline now preserves Display P3 and HDR color all the way to the platform renderer. DeferredAnimatedContent and DeferredAnimatedVisibility enable two-phase transitions that hand off from a gesture-driven phase to a triggered animation, built for predictive back.

BasicTextField gains programmatic rich-text formatting through TextFieldBuffer, and SelectionState exposes selectAll, clear, and cross-container text selection. Credential Manager hooks into text fields via a new credentialRequest semantic property. On the testing side, hasPendingWork and runWithoutImplicitWait let tests drive animation frames manually without implicit sync overhead, and Compose's time-to-initial-display now matches View in benchmarks.

Takeaways
Compose 1.12 bumps compileSdk to API 37 and requires AGP 9.1.1; upgrading forces Kotlin and Android Studio updates in lockstep.
Modifier.onFirstVisible() is deprecated; migrate to Modifier.onVisibilityChanged() for precise threshold tracking.
The experimental Styles API changed the size function and does not guarantee binary compatibility — old libraries calling it can crash at runtime in a project that upgrades Compose.
A new keyed SideEffect overload runs one-shot effects without coroutines, up to 90% faster than LaunchedEffect and about 20% faster than DisposableEffect.
SideEffect executes earlier than LaunchedEffect and DisposableEffect; migrations that depend on post-frame scheduling can break.
MeshGradientPainter creates multi-control-point gradients with setVertex calls specifying row, column, position, and color.
The graphics pipeline now preserves Display P3 and HDR color through to the platform renderer, falling back to sRGB on unsupported color spaces or Android 9 and below.
GraphicsLayer and Modifier.graphicsLayer gain LayerOutsets to let visual bounds exceed measured size, avoiding implicit clipToBounds on offscreen buffers.
DeferredAnimatedContent and DeferredAnimatedVisibility create two-phase transitions: a manually controlled deferred phase followed by a smooth engine takeover with velocity transfer.
SharedContentConfig adds permitTransformDuringDeferredTransition to control whether shared elements transform during the deferred phase.
BasicTextField gets programmatic rich-text formatting via TextFieldBuffer.addStyle() with SpanStyle and ParagraphStyle; formatting survives configuration changes.
SelectionState exposes selectAll(), clear(), select(TextRange), extendSelectionByWord(), and cross-SelectionContainer text selection via getSelectableTexts().
Text fields integrate with Android Credential Manager through a credentialRequest semantic property and CredentialRequestData.
Experimental Grid supports named areas defined in GridConfigurationScope, replacing numeric row/column indices with area IDs.
Compose's time-to-initial-display now matches View in benchmarks.
hasPendingWork checks for pending UI work without advancing the clock; runWithoutImplicitWait disables implicit sync during manual frame stepping.
captureToImage can capture a popup or dialog together with its anchor into one bitmap.
onRootWithViewInteraction restricts Compose semantics-tree searches to a given Android View, simplifying RecyclerView tests.
@PreviewWrapper enables reusable Preview configurations across multiple @MultiPreview classes.
Downloadable fonts support variation settings; KeyboardType adds Date, Time, DateTime, and SignedDecimal.
BasicSecureTextField defaults to TextObfuscationMode.System; RevealLastTyped forces the last typed character to remain visible.
Conclusions

The Styles API's binary-incompatibility is a real dependency-management hazard: a library compiled against an older Compose can silently crash a newer app, and the compiler won't catch it. This is the kind of runtime risk that erodes trust in experimental APIs.

Keyed SideEffect fills a gap that should have been obvious from day one — the only way to run a one-shot composition effect was to pay the coroutine tax with LaunchedEffect(Unit). Arriving at 1.12 suggests the Compose team deprioritized it for years.

The Styles API now competes with Modifier and TextStyle for the same styling surface on BasicText. Three overlapping control paths for one component is a design smell that will confuse newcomers and fragment codebases unless Google converges them.

Compose matching View on time-to-initial-display removes the last credible performance objection to adopting Compose for cold-start-sensitive apps. The benchmark data makes the case stronger than any marketing claim.

DeferredAnimatedContent is effectively a predictive-back animation primitive dressed as a general-purpose API. Its real utility is narrow but critical for Android's gesture-navigation UX requirements.

Concepts & terms
MeshGradientPainter
A Compose painter that creates gradients defined by a grid of control points, each with its own position and color, producing smoother, more natural color transitions than linear or radial gradients.
Wide Color Gamut (P3)
A color space — specifically Display P3 — that can represent more saturated colors than sRGB. Compose 1.12 preserves P3 color data through the rendering pipeline instead of clamping to sRGB.
LayerOutsets
A property on GraphicsLayer that lets a layer's visual bounds extend beyond its measured size, preventing implicit clipping when the layer is promoted to an offscreen buffer.
DeferredAnimatedContent
A Compose animation API that splits a transition into two phases: a manually controlled deferred phase (e.g., following a swipe gesture) and an automatic phase that smoothly takes over with velocity transfer.
TextFieldBuffer
The mutable text buffer backing BasicTextField. In Compose 1.12 it gains addStyle(), getSpanStyles(), and getParagraphStyles() for programmatic rich-text formatting.
CredentialRequestData
A data class passed to a text field's credentialRequest semantic property to integrate Android's Credential Manager for Passkey and saved-credential prompts during input.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗