Skip to content

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

Merged
dkhawk merged 3 commits into
mainfrom
fix/marker-info-window-viewtree-lifecycle-owner
Aug 26, 2026
Merged

fix: pin ViewTreeLifecycleOwner/SavedStateRegistryOwner on MapView to prevent info window crash#972
dkhawk merged 3 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

@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
kikoso added 2 commits August 26, 2026 09:05
… 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.
@kikoso
kikoso force-pushed the fix/marker-info-window-viewtree-lifecycle-owner branch from 7f1347b to 29e5939 Compare August 26, 2026 02:06

@LoyalAbbas LoyalAbbas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dkhawk
dkhawk merged commit 4024515 into main Aug 26, 2026
13 checks passed
@dkhawk
dkhawk deleted the fix/marker-info-window-viewtree-lifecycle-owner branch August 26, 2026 18:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants