android-maps-compose icon indicating copy to clipboard operation
android-maps-compose copied to clipboard

Can't change the default clusterItemContent (java.lang.IllegalStateException: Invalid applier)

Open Youssef3ssamProgressio opened this issue 2 years ago • 9 comments

I am facing an Invalid applier error while using Jetpack Compose in conjunction with Google Maps clustering for custom markers.


Dependencies

implementation("com.google.maps.android:maps-compose:2.15.0")
implementation("com.google.maps.android:maps-compose-utils:2.15.0")

Steps to reproduce

  1. Use Jetpack Compose with Google Maps clustering.
  2. Add the following sample at MapClusteringActivity
// Optional: Custom rendering for non-clustered items
            clusterItemContent = {
                Marker(
                    state = MarkerState(position = it.itemPosition),
                    title = "Title",
                    snippet = "Snippet"
                )
            }

Expected Behavior:

I expect the Google Maps clustering to properly display the custom markers using Jetpack Compose, without facing any errors related to invalid appliers.


Code example

@OptIn(MapsComposeExperimentalApi::class)
@Composable
private fun ShowStations(stations: List<Station>) {
    Clustering(
        items = stations,
        onClusterClick = { true },
        onClusterItemClick = { true },
        onClusterItemInfoWindowClick = { },
        clusterContent = null,
        clusterItemContent = {
            Marker(
                state = rememberMarkerState(position = it.position),
                icon = bitmapDescriptor(LocalContext.current, R.drawable.ic_map_marker_default)
            )
        }
    )
}

Stack trace

FATAL EXCEPTION: main
java.lang.IllegalStateException: Invalid applier
    at androidx.compose.runtime.ComposablesKt.invalidApplier(Composables.kt:472)
    at com.google.maps.android.compose.MarkerKt.MarkerImpl-rwhEA70(Marker.kt:518)
    at com.google.maps.android.compose.MarkerKt.Marker-ln9Ul-Y(Marker.kt:172)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:117)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
    at com.google.maps.android.compose.clustering.ComposeUiClusterRenderer$createAndAddView$view$2.invoke(ClusterRenderer.kt:95)
    at com.google.maps.android.compose.clustering.ComposeUiClusterRenderer$createAndAddView$view$2.invoke(ClusterRenderer.kt:95)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
    at com.google.maps.android.compose.clustering.ComposeUiClusterRenderer$InvalidatingComposeView.Content(ClusterRenderer.kt:220)
    at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:252)
    at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:251)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
    at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
    at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:195)
    at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:119)
    at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:118)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
    at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
    at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:110)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:158)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:157)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
    at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:157)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:142)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
    at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:78)
    at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3340)
    at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3273)
    at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:588)
    at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1013)
    at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4007)
    at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:520)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:142)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133)
    at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1191)
    at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:133)
    at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:183)
    at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.kt:314)
    at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.kt:192)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:140)
    at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133)
    at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1266)
    at android.view.View.dispatchAttachedToWindow(View.java:21290)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3491)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3498)
    at android.view.ViewGroup.addViewInner(ViewGroup.java:5291)
    at android.view.ViewGroup.addView(ViewGroup.java:5077)
    at android.view.ViewGroup.addView(ViewGroup.java:5017)
    at android.view.ViewGroup.addView(ViewGroup.java:4989)
    at com.google.maps.android.compose.MapComposeViewRenderKt.startRenderingComposeView(MapComposeViewRender.kt:46)
    at com.google.maps.android.compose.MapComposeViewRenderKt$rememberComposeUiViewRenderer$1$1.startRenderingView(MapComposeViewRender.kt:92)
    at com.google.maps.android.compose.clustering.ComposeUiClusterRenderer.createAndAddView(ClusterRenderer.kt:99)
    at com.google.maps.android.compose.clustering.ComposeUiClusterRenderer.onClustersChanged(ClusterRenderer.kt:67)
    at com.google.maps.android.clustering.ClusterManager$ClusterTask.onPostExecute(ClusterManager.java:320)
    at com.google.maps.android.clustering.ClusterManager$ClusterTask.onPostExecute(ClusterManager.java:306)
    at android.os.AsyncTask.finish(AsyncTask.java:771)
    at android.os.AsyncTask.-$$Nest$mfinish(Unknown Source:0)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:788)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:7872)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

Youssef3ssamProgressio avatar Sep 26 '23 23:09 Youssef3ssamProgressio

If you would like to upvote the priority of this issue, please comment below or react on the original post above with :+1: so we can see what is popular when we triage.

@Youssef3ssamProgressio Thank you for opening this issue. 🙏 Please check out these other resources that might help you get to a resolution in the meantime:

This is an automated message, feel free to ignore.

wangela avatar Sep 27 '23 00:09 wangela

me too, cannot add Marker in clusterItemContent, currently proceed with image as Marker, and then drop performance in Image Markers count with 1800+ , a little latency in pinch and zoom.

htooaunghlaing-cdg avatar Sep 27 '23 06:09 htooaunghlaing-cdg

the cluster content lambda cannot take a Marker composable, but expects just a plain composable. (no handling of marker state) this however has major drawbacks as you cannot configure properties of the Marker (like anchor or zIndex) when using a cluster.

cwsiteplan avatar Oct 02 '23 06:10 cwsiteplan

update: latest release does add zIndex handling to clusters.

cwsiteplan avatar Oct 09 '23 08:10 cwsiteplan

@cwsiteplan How are you applying a zIndex to the cluster items? I'm on 4.3.0 and I see no such property on the Clustering Composable, and I run into the original Invalid applier issue if I try to use a Marker with a zIndex.

tcoxMonkeyCoder avatar Nov 28 '23 15:11 tcoxMonkeyCoder

do you mean version 4.3.0 ? (latest) or really 3.4.0 - which is quite old an does not have the capability.

the com.google.maps.android.clustering.ClusterItem now has getZIndex() which can be override by your cluster item

cwsiteplan avatar Nov 28 '23 15:11 cwsiteplan

@cwsiteplan Sorry for the typo, yes I'm on 4.3.0 and getZIndex() solved my problem. I guess I was assuming it would be a parameter on the composable for some reason, but makes sense to be on the item. Thank you!

tcoxMonkeyCoder avatar Nov 28 '23 18:11 tcoxMonkeyCoder

facing this issue too

feivur avatar Apr 03 '24 12:04 feivur

This probably won't get fixed or will it?

Would be nice to get a proper solution, instead of applying Projected content as a InfoWindowContent, since I really wanted to use MarkerInfoWindowContent

Lizzergas avatar Sep 06 '25 18:09 Lizzergas