Skip to content
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

Markers are duplicating on map view #577

Closed
GaniduAsh opened this issue Jun 4, 2024 · 2 comments
Closed

Markers are duplicating on map view #577

GaniduAsh opened this issue Jun 4, 2024 · 2 comments
Labels
triage me I really want to be triaged. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.

Comments

@GaniduAsh
Copy link

GaniduAsh commented Jun 4, 2024

compose-mapview version = 5.0.1

I am using CustomUiClustering as a reference to render custom markers on my application's map view. However, I have noticed a weird behavior intermittently, as sometimes markers are duplicated (please refer to the attached image).

Due to this weird behavior, clicking on one of the markers leads to an app crash. (crash log is attached)

Steps to reproduce

  1. Open the map screen and render markers on mapview

Code example

1. Mapview configuration 
val mapProperties by remember {
        mutableStateOf(
            MapProperties(
                mapType = MapType.NORMAL,
                isMyLocationEnabled =  true
            )
        )
    }

    val mapUiSettings by remember {
        mutableStateOf(
            MapUiSettings(
                compassEnabled = false,
                zoomControlsEnabled = true,
                mapToolbarEnabled = false,
                myLocationButtonEnabled = false
            )
        )
    }


2. How  markers are rendered in mapview
@Composable
@OptIn(MapsComposeExperimentalApi::class)
private fun CustomUiClustering(items: List<ClusterItem>) {
    Clustering(
        items = items,
        // Optional: Handle clicks on clusters, cluster items, and cluster item info windows
        onClusterClick = {
            //Log.d(TAG, "Cluster clicked! $it")
            false
        },
        onClusterItemClick = {
            //Log.d(TAG, "Cluster item clicked! $it")
            false
        },
        onClusterItemInfoWindowClick = {
            //Log.d(TAG, "Cluster item info window clicked! $it")
        },
        // Optional: Custom rendering for clusters
        clusterContent = { cluster ->
            ClusterContentUI(
                size = cluster.size
            )
        },
        // Optional: Custom rendering for non-clustered items
        clusterItemContent = {
            MarkerItemUI(
                item = it
            )
        }
    )
}
# example

Upon clicking on one of the marker item, follow crash occurs

 java.lang.NullPointerException: Parameter specified as non-null is null: method .ui.map.MapViewUIKt$CustomUiClustering$2.invoke, parameter it
                                                                                                    	at com.x.map.MapViewUIKt$CustomUiClustering$2.invoke(Unknown Source:2)
                                                                                                    	at com.x.map.MapViewUIKt$CustomUiClustering$2.invoke(MapViewUI.kt:208)
                                                                                                    	at com.google.maps.android.compose.clustering.ClusteringKt$Clustering$12.invoke$lambda$1(Clustering.kt:140)
                                                                                                    	at com.google.maps.android.compose.clustering.ClusteringKt$Clustering$12.$r8$lambda$FW9IFdH-eY05BJYZl-3m-J_d02I(Unknown Source:0)
                                                                                                    	at com.google.maps.android.compose.clustering.ClusteringKt$Clustering$12$$ExternalSyntheticLambda1.onClusterItemClick(D8$$SyntheticClass:0)
                                                                                                    	at com.google.maps.android.clustering.view.DefaultClusterRenderer$1.onMarkerClick(DefaultClusterRenderer.java:153)
                                                                                                    	at com.google.maps.android.collections.MarkerManager.onMarkerClick(MarkerManager.java:100)
                                                                                                    	at com.google.maps.android.compose.clustering.ClusteringKt$Clustering$14.invoke(Clustering.kt:168)
                                                                                                    	at com.google.maps.android.compose.clustering.ClusteringKt$Clustering$14.invoke(Clustering.kt:168)
                                                                                                    	at com.google.maps.android.compose.MapApplier.attachClickListeners$lambda$21(MapApplier.kt:304)
                                                                                                    	at com.google.maps.android.compose.MapApplier.$r8$lambda$QenMknOiW0LWHUw6keUfWjCiuhc(Unknown Source:0)
                                                                                                    	at com.google.maps.android.compose.MapApplier$$ExternalSyntheticLambda4.onMarkerClick(D8$$SyntheticClass:0)
                                                                                                    	at com.google.android.gms.maps.zza.zzb(com.google.android.gms:play-services-maps@@18.2.0:1)
                                                                                                    	at com.google.android.gms.maps.internal.zzau.zza(com.google.android.gms:play-services-maps@@18.2.0:3)
                                                                                                    	at com.google.android.gms.internal.maps.zzb.onTransact(com.google.android.gms:play-services-maps@@18.2.0:3)
                                                                                                    	at android.os.Binder.transact(Binder.java:1043)
                                                                                                    	at cx.a(:com.google.android.gms.dynamite_mapsdynamite@201817048@20.18.17 (040400-0):2)
                                                                                                    	at com.google.maps.api.android.lib6.impl.da.b(:com.google.android.gms.dynamite_mapsdynamite@201817048@20.18.17 (040400-0):3)
                                                                                                    	at com.google.maps.api.android.lib6.gmm6.api.f.b(:com.google.android.gms.dynamite_mapsdynamite@201817048@20.18.17 (040400-0):7)
                                                                                                    	at com.google.maps.api.android.lib6.gmm6.vector.l.a(:com.google.android.gms.dynamite_mapsdynamite@201817048@20.18.17 (040400-0):20)
                                                                                                    	at com.google.maps.api.android.lib6.gmm6.vector.af.b(:com.google.android.gms.dynamite_mapsdynamite@201817048@20.18.17 (040400-0):16)
                                                                                                    	at com.google.maps.api.android.lib6.gmm6.vector.cq.onSingleTapConfirmed(:com.google.android.gms.dynamite_mapsdynamite@201817048@20.18.17 (040400-0):0)
                                                                                                    	at com.google.maps.api.android.lib6.impl.gesture.b.onSingleTapConfirmed(:com.google.android.gms.dynamite_mapsdynamite@201817048@20.18.17 (040400-0):0)
                                                                                                    	at com.google.maps.api.android.lib6.impl.gesture.c.handleMessage(:com.google.android.gms.dynamite_mapsdynamite@201817048@20.18.17 (040400-0):4)
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                                                    	at android.os.Looper.loop(Looper.java:223)
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:7656)
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method)
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

# example

map_view_isse

Is there anything i can do to overcome with this issue?

Thanks!

@GaniduAsh GaniduAsh added triage me I really want to be triaged. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. labels Jun 4, 2024
@bleeding182
Copy link

I just encountered the same issue. I could reproduce it in 4.3.0 and updating to 6.1.0 also does not fix it.

I can't reliably reproduce the issue either. When entering/exiting a map screen they sometimes appear. This affects both, cluster markers (blue bubble) as well as normal markers (red default pin). And both will crash on click due to the tag not being set.
image
image

Moving/zooming the map and having the markers cluster and separate does not remove or update those markers either, they just stay around, so it appears like they have been leaked.

@GaniduAsh
Copy link
Author

GaniduAsh commented Jul 16, 2024

@bleeding182 bleeding182

I was able to fix this by updating the rendering the algorithm. Basically using NonHierarchicalViewBasedAlgorithm will allow to load markers upon panning the map view

val configuration = LocalConfiguration.current
   val screenHeight = configuration.screenHeightDp.dp
   val screenWidth = configuration.screenWidthDp.dp
   val clusterManager = rememberClusterManager<ClusterItem>()

   // Here the clusterManager is being customized with a NonHierarchicalViewBasedAlgorithm.
   // This speeds up the rendering of items on the screen and enables progressive rendering.
   clusterManager?.setAlgorithm(
       NonHierarchicalViewBasedAlgorithm(
           screenWidth.value.toInt(),
           screenHeight.value.toInt()
       )
   )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triage me I really want to be triaged. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
2 participants