-
Notifications
You must be signed in to change notification settings - Fork 149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Return early in rememberComposeBitmapDescriptor for invalid view size #533
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The end result of this change is that the map will render the default marker instead of crashing on an empty composable marker. This would seem to hide the problem in a workaround, rather than flag it. Would throwing a more meaningful exception help with troubleshooting here?
Just my 2 cents here: creating an empty ComposeView suggests some kind of problem in user code. I imagine user code may be able to avoid creating the marker entirely by testing whether necessary preconditions are met before attempting to create the marker.
@@ -51,6 +51,11 @@ private fun renderComposableToBitmapDescriptor( | |||
View.MeasureSpec.makeMeasureSpec(parent.height, View.MeasureSpec.AT_MOST), | |||
) | |||
|
|||
if(composeView.measuredWidth == 0 || composeView.measuredHeight == 0) { | |||
parent.removeView(composeView) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can avoid the extra removeView() by adding try-finally in the right place here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback! Yeah, unfortunately I am not sure why this happens in the first place. Maybe some race condition while navigating? I can't dig into it as this happens super rarely and I was not able to reproduce it while having the debugger attached.
I don't think that a different error would help here as we already know that the problem is an incorrect view size. The question is just why we get to this state. As you can see from the example code in the issue, the original reporter only uses the GoogleMaps composable and adds some markers (the same as I do in my code). I don't see what we as users of this library could do differently as the code works >99% of the time. Or could we add any meaningful information to a new exception which would help finding the root cause?
For now, not providing a custom icon at all in this edge case was the best solution for me as it at least does not cause crashes in production.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if you used Modifier.requiredSizeIn()
on your marker composable content with a minimum of 1.dp or so, as an alternative workaround? I'd be curious if you still crash then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ln-12 Actually, I suspect that setting a minimum size on the composable, like I suggested above, would not make a difference.
Here is the problem that I think may be at the root of this issue (have not tested it):
Lines 50 to 51 in 0599412
View.MeasureSpec.makeMeasureSpec(parent.width, View.MeasureSpec.AT_MOST), | |
View.MeasureSpec.makeMeasureSpec(parent.height, View.MeasureSpec.AT_MOST), |
A parent view dimension of 0 would cause this crash, no matter how large the Composable wants to be.
I'd think the parent view here would commonly be the Activity's top ComposeView, or supposedly something else in case of navigation, etc. So the maximum marker icon size would commonly be constrained by the size of the screen, which looks weird to me, as that could be quite large.
A better approach, short of workarounds, may be to use View.MeasureSpec.UNSPECIFIED
here; restricting marker size by screen size just does not look that useful, it's way too big, creating giant bitmaps. However, I imagine this change would be breaking, as there is no max size anymore. Yet a marker composable relying on something like fillMaxSize is not doing it right, it needs to use something more specific. There may be other concerns with UNSPECIFIED, however, not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. I can force the crash by setting the size of the fragment which contains the compose view to 0 (but I am still not sure when this happens while navigating): https://github.com/ln-12/GoogleMapsCrashReproducer/blob/main/app/src/main/res/layout/activity_main.xml#L11-L12
With that, I also tested View.MeasureSpec.UNSPECIFIED
and for me it did not crash anymore. I can change my PR to use this spec, but just like you, I am not sure about other side effects when doing so.
So what would you suggest going forward?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be documented inline with the code or only as a release note in the changelog?
The requirement for the Composable to have a non-null size in both dimensions, and the absence of a parent size need to be documented in public API KDoc documentation on MarkerComposable()
. Also in release notes, I believe this would be a task for project maintainers, e.g. @kikoso or @dkhawk.
It could also be flagged prominently in code; personally I'd check for this case after measure()
and throw an exception of some sort if measure returns 0 for one or both of the dimensions. This way the problem is identified in a well-defined manner if it happens with the ability to give specific instructions on what to do (set a size in the Composable).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What @bubenheimer describer: the expectation is to have the documentation incode from the PR. The release notes can be manually updated to reflect any other relevant changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, I meant "absence of a parent size", not "absence of a parent".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bubenheimer Unfortunately, we now get crashes containing the exact exception from this PR. We use version 6.1.2
of this library. Do you have another idea how this could be solved? Before we forked this lib and implemented an early return which might have led to undesired results but at least did not crash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ln-12 might be best to create a new issue with stacktrace so a maintainer can look at it.
You need to ensure that the content Composable that you are drawing for the Marker always has a non-zero size. Like setting a minimum size of (1,1) via a Modifier. If that does not work for some reason, maybe add some sort of canvas with a single transparent pixel?
@ln-12 hi. Thank you for this contribution Please add semantic prefixes to commits |
maps-compose/src/main/java/com/google/maps/android/compose/RememberComposeBitmapDescriptor.kt
Outdated
Show resolved
Hide resolved
…sable is zero sized
c679916
to
62c313d
Compare
I added the commit prefixes and applied all requested changes. If you are not yet happy with the wording, please let me know. |
|
||
if (composeView.measuredWidth == 0 || composeView.measuredHeight == 0) { | ||
throw IllegalStateException("The ComposeView was measured to have a width or height of " + | ||
"zero. Make sure the parent and content have a non-zero size.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to your testing, "parent" size should no longer matter, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, right. I changed that.
6a838ba
to
81423e7
Compare
I was using the wrong mail for my last commit (as I was on a different machine), so the CLA check failed. Fixed that as well. Sorry for the inconvenience! |
Hey @dkhawk, is there any open TODO on my side? We would highly appreciate getting this fix rolled out 😅 |
🎉 This PR is included in version 5.0.4 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
# [6.0.0](v5.0.3...v6.0.0) (2024-07-03) ### Bug Fixes * fix release step ([#586](#586)) ([e5dc195](e5dc195)) * leverage `@StateFactoryMarker` to flag State object creation without remember or similar mechanisms. ([#516](#516)) ([9ed3f7a](9ed3f7a)), closes [#506](#506) * Return early in rememberComposeBitmapDescriptor for invalid view size ([#533](#533)) ([db97e65](db97e65)) ### BREAKING CHANGES * leverage @StateFactoryMarker to flag State object creation without remember or similar mechanisms Co-authored-by: Uli Bubenheimer <bubenheimer@users.noreply.github.com>
🎉 This issue has been resolved in version 6.0.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
Fixes #518 🦕
By returning early in the case of invalid view width/height, we can avoid the IllegalArgumentException described in issue #518.