Skip to content

fix: pin ViewTreeLifecycleOwner/SavedStateRegistryOwner on MapView to prevent info window crash - #972

Open
kikoso wants to merge 2 commits into
mainfrom
fix/marker-info-window-viewtree-lifecycle-owner
Open

fix: pin ViewTreeLifecycleOwner/SavedStateRegistryOwner on MapView to prevent info window crash#972
kikoso wants to merge 2 commits into
mainfrom
fix/marker-info-window-viewtree-lifecycle-owner

Conversation

@kikoso

@kikoso kikoso commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes #971.

On compose-ui 1.11+, MarkerInfoWindow / MarkerInfoWindowContent can crash with:

java.lang.IllegalStateException: Composed into the View which doesn't propagate ViewTreeLifecycleOwner!

The Maps SDK measures the info-window ComposeView from its own Handler, asynchronously. If that measure lands after Compose has unparented the MapView (e.g. LazyColumn recycling/detach), the ComposeView can no longer resolve a ViewTreeLifecycleOwner/ViewTreeSavedStateRegistryOwner by walking up its ancestors, because those tags live on the AndroidView holder — the MapView's parent — not on the MapView itself. AbstractComposeView.onMeasure then throws (this became fatal in compose-ui 1.11, which moved owner resolution into onMeasure; on 1.10 it silently rendered blank instead).

Fix

Two commits:

  1. Pin the ViewTree owners onto the MapView (GoogleMap.kt) — at creation in the AndroidView factory, and on every update in case the owner identity changes. This keeps the owner lookup resolvable from within the map's own subtree regardless of where Compose has parented the MapView, without changing behavior while attached (same owner instances AndroidView already assigns to the parent).

  2. Handle the now-reachable zero-size render gracefully (MapComposeViewRender.kt, ComposeInfoWindowAdapter.kt) — with (1) alone, the original crash is gone, but on this codebase's bitmap-based info-window rendering (fix: avoid re-parenting crash for MarkerInfoWindowContent/MarkerInfoWindowComposable #953) the same detached-render race surfaces a second crash: renderComposableToBitmap's own check() rejects the zero-size measurement that naturally results from compositing a ComposeView that never got a real window attachment. A MapView mid-teardown has nothing worth rendering anyway, so that specific case (zero-size and not attached to window) now returns null instead of throwing, propagated through the already-nullable getInfoContents()/getInfoWindow(). Zero-size content on an attached MapView still throws with the original message — that's a genuine content-authoring bug, not a teardown race.

Test plan

🤖 Generated with Claude Code

kikoso added 2 commits August 20, 2026 21:33
… prevent info window crash

On compose-ui 1.11+, MarkerInfoWindow/MarkerInfoWindowContent can crash with
"Composed into the View which doesn't propagate ViewTreeLifecycleOwner!" when
the Maps SDK measures the info window's ComposeView from its own Handler after
Compose has already unparented the MapView (e.g. LazyColumn recycling/detach).

The ViewTreeLifecycleOwner/ViewTreeSavedStateRegistryOwner tags live on the
AndroidView holder that is the MapView's parent, so once that parent link is
severed the info window's ComposeView can no longer resolve an owner and
AbstractComposeView.onMeasure throws (fatal starting with compose-ui 1.11,
where owner resolution moved into onMeasure).

Pin both owners directly onto the MapView itself so they stay resolvable from
its own subtree regardless of where Compose has parented it.

Fixes #971
The pin added in the previous commit stops the Maps SDK's async info-window
render from throwing "Composed into the View which doesn't propagate
ViewTreeLifecycleOwner!" once Compose has unparented the MapView. But on
this codebase's bitmap-based info window rendering (#953), that same
detached-render path now hits a different crash: renderComposableToBitmap's
own check() rejects the zero-size measurement that naturally results from
compositing a ComposeView that never got a real window attachment.

A MapView that's mid-teardown has nothing worth rendering anyway, so treat
that specific case (zero-size AND not attached to window) as "nothing to
show" instead of a hard failure: renderComposableToBitmap now returns null,
and ComposeInfoWindowAdapter propagates that through to the Maps SDK's
already-nullable getInfoContents()/getInfoWindow(). Zero-size content on an
attached MapView still throws with the original message, since that is a
genuine content-authoring bug rather than a teardown race.

Verified on a physical device (Pixel 4, Android 13, GMS 26.32.62, phoenix
renderer) using the exact LazyColumn-recycling repro from #971: crashes
within the first ~20 cycles without both fixes, survives 420+ cycles
(60s, process alive throughout) with both applied.
@googlemaps-bot

googlemaps-bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Code Coverage

Overall Project 25.74%

There is no coverage information present for the Files changed

@kikoso
kikoso marked this pull request as ready for review August 20, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants