Animation Performance Fix (Android) - #134
Open
tifroz wants to merge 6 commits into
Open
Conversation
7 tasks
Contributor
Author
|
@marcprux pinging you for a code review (not urgent, but I think this may have fallen through the cracks) |
- Add androidCompositionBoundary(id:inputs:) for retained Android composition roots - Add androidEquatable wrappers to skip parent-driven recomposition - Remove the graphicsLayerOffset bridge
- retain composition-boundary projections by instance and inputs - preserve full Swift equality in androidEquatable - add compositor and experimental first-render modifiers - document Android recomposition controls and add regression tests
- verify replacing boundary inputs releases the previous projection - verify the replacement remains retained until the boundary releases it - document that bridged content inherits its environment and parent sizing
tifroz
force-pushed
the
experimental_animation-performance
branch
from
August 22, 2026 20:35
f3b3673 to
3d04364
Compare
Member
|
Apologies for the delay; I expect to be able to start getting back to reviewing the bigger PRs that have piled up. Just checking whether this is ready for review? I ask only because you just pushed a few more commits… |
Contributor
Author
|
Yes it is ready for review along the SkipUI companion (the last update was just adding some tests + documentation clarifications to tighten things up, no changes to the codebase) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thank you for contributing to the Skip project! Please use this space to describe your change and add any labels (bug, enhancement, documentation, etc.) to help categorize your contribution.
Please review the contribution guide at https://skip.dev/docs/contributing/ for advice and guidance on making high-quality PRs.
Skip Pull Request Checklist:
swift testCodex generated the code with supervision, UI tests conducted manually to validate performance improvements
Summary
Animations on Android can become choppy in complex UI hierarchies when an animated state change causes unrelated subtrees to be reevaluated, re-bridged, or recomposed. That additional work competes with rendering animated frames.
androidEquatable,androidCompositionBoundaryThis PR adds two explicit Android recomposition controls:
androidEquatableacts as an update gate. It skips reevaluating and re-bridging a subtree while its supplied SwiftEquatablevalue remains unchanged.androidCompositionBoundarygives a subtree its own retained Compose identity and lifecycle. Stableidandinputsvalues reuse its existing projection, while changed inputs update its content without replacing the retained host.These APIs serve different purposes: use
androidEquatableto avoid unnecessary evaluation of ordinary UI, andandroidCompositionBoundaryfor independently retained content such as WebViews, maps, or video surfaces.compositorTransformcompositorTransformapplies scale and translation in a single Android graphics layer without relocating the Compose layout node. This is useful for native-backed surfaces such as WebViews, where keeping layout identity stable during animation avoids unnecessary layout and lifecycle work.Usage Example
Use
androidEquatablewhen a subtree can update as a unit and should only be reevaluated when its inputs change:Use
androidCompositionBoundarywhen a subtree such as a WebView, map, or video surface needs independently retained identity and lifecycle:Use
compositorTransformwhen native-backed content such as a WebView must scale and translate in one Android compositor layer:API Shape
Notes
This PR depends on skiptools/skip-ui#500
androidCompositionBoundarycallers must keepidstable for retained identity and include every parent-driven update ininputscompositorTransformchanges rendered pixels without changing layout geometry; callers that need layout movement should continue using the standard layout modifierscompositorTransformis intentionally distinct from chainingscaleEffectandoffset: on Android those modifiers use separate graphics-layer and placement operations, while native-backed content such as WebViews needs scale and translation fused into one compositor layer so the Compose layout node remains stationarytifroz/skip-ui:experimental_animation-performancebranch and should move back to a released SkipUI dependency after the paired SkipUI PR lands