Skip to content

fix: avoid re-parenting crash for MarkerInfoWindowContent/MarkerInfoWindowComposable - #953

Merged
kikoso merged 1 commit into
mainfrom
fix/info-window-content-crash
Aug 6, 2026
Merged

fix: avoid re-parenting crash for MarkerInfoWindowContent/MarkerInfoWindowComposable#953
kikoso merged 1 commit into
mainfrom
fix/info-window-content-crash

Conversation

@kikoso

@kikoso kikoso commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Fixes #950

Summary

PR #931 fixed #913 (empty info window content on compose-ui 1.10+) by keeping the ComposeView permanently attached to the library's own container while the info window is shown. That works around compose-ui's attachment requirement for drawing, but it means the view handed back from getInfoContents()/getInfoWindow() already has a parent. The Maps SDK internally re-parents that view into its own default info window frame, so calling addView() on an already-parented view throws:

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

This crash reproduces on device every time a MarkerInfoWindowContent marker is tapped, matching what is reported in #950.

Fix

Render the Compose content into a plain Bitmap up front (attach, measure, layout, draw, detach), the same technique already used and proven for MarkerComposable icon bitmaps, and hand the Maps SDK a fresh, unattached ImageView wrapping that bitmap instead of the live ComposeView.

This keeps the compose-ui 1.10+ fix from #931 (content is fully rendered before we let go of it) while avoiding the double parent crash, since the returned view was never attached anywhere for the SDK to conflict with.

Test plan

@googlemaps-bot

Copy link
Copy Markdown
Contributor

Code Coverage

Overall Project 25.82%

There is no coverage information present for the Files changed

@LoyalAbbas
LoyalAbbas self-requested a review August 6, 2026 04:15

@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

…indowComposable

Fixes #950

PR #931 fixed #913 (empty info window content on compose-ui 1.10+) by
keeping the ComposeView permanently attached to the library's own
container while the info window is shown. That works around
compose-ui's attachment requirement for drawing, but it means the view
handed back from getInfoContents()/getInfoWindow() already has a
parent. The Maps SDK internally re-parents that view into its own
default info window frame, so calling addView() on an already-parented
view throws:

java.lang.IllegalStateException: The specified child already has a
parent. You must call removeView() on the child's parent first.

This change renders the Compose content into a plain Bitmap up front
(attach, measure, layout, draw, detach, the same technique already
used for MarkerComposable icon bitmaps) and hands the Maps SDK a
fresh, unattached ImageView wrapping that bitmap instead of the live
ComposeView. This keeps the compose-ui 1.10+ fix from #931 (content is
fully rendered before we let go of it) while avoiding the double
parent crash, since the returned view was never attached anywhere.

Verified on a physical device: reproduced the #950 crash on the
previous build, confirmed it is gone after this change, and confirmed
MarkerInfoWindowContent and MarkerInfoWindowComposable content still
render correctly under compose-bom 2026.06.01 (compose-ui 1.10+),
covering the original #913 scenario as well.
@kikoso
kikoso force-pushed the fix/info-window-content-crash branch from cdab586 to 71ab241 Compare August 6, 2026 15:10
@kikoso
kikoso merged commit 12f35a4 into main Aug 6, 2026
13 of 14 checks passed
@kikoso
kikoso deleted the fix/info-window-content-crash branch August 6, 2026 15:59
kikoso added a commit that referenced this pull request Aug 20, 2026
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 added a commit that referenced this pull request Aug 26, 2026
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.
dkhawk added a commit that referenced this pull request Aug 26, 2026
… prevent info window crash (#972)

* fix: pin ViewTreeLifecycleOwner/SavedStateRegistryOwner on MapView to 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

* fix: don't crash rendering an info window for a MapView mid-teardown

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.

---------

Co-authored-by: Dale Hawkins <107309+dkhawk@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants