简体   繁体   中英

How update markers on Map when using ClusterManager

I am trying to update my map with newer data from server but I can't figure out how to remove old items ( markers and cluster - Using ClusterManager ) from map ( - seems to me that I can only add in ClusterManager.

I have BroadcastReceiver which get intent when there are new data. I was trying something like this: ( but it gives me UnsupportedOperationException on line with "...getMarkers().clear();"

private BroadcastReceiver myRefrestMapBroadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive");
        mClusterManager.clearItems();
        mClusterManager.getMarkerCollection().getMarkers().clear();
        mClusterManager.getClusterMarkerCollection().getMarkers().clear();
        mClusterManager.addItems(LocationGetter.getReports());
    }
};

I added data to map only with this function.

java.util.Collection<Marker> userCollection = mClusterManager.getMarkerCollection().getMarkers();
            ArrayList<Marker> userList = new ArrayList<Marker>(userCollection);
            // now is userList empty
            for(Marker marker: userList){
                marker.remove();
            }

            java.util.Collection<Marker> userCollection2 = mClusterManager.getClusterMarkerCollection().getMarkers();
            ArrayList<Marker> userList2 = new ArrayList<Marker>(userCollection2);
            // now is userList2 empty
            for(Marker marker: userList2){
                marker.remove();
            }

            mClusterManager.addItems(LocationGetter.getReports());

According to ClusterManager documentation , we can use mClusterManager.cluster();

This method Force a re-cluster. You may want to call this after adding new item(s).

I was concentrating the whole time on ClusterManager, so I forgot about GoogleMap , and specifically the method clear() . I was able to solve the problem with this code:

mGoogleMap.clear();
mClusterManager.clearItems();  // calling just in case (may not be needed)
mClusterManager.addItems(LocationGetter.getReports());

There isn't any API to notify that a cluster item has been updated. But you can use clusterManager.removeItem() + clusterManager.addItem() to force an update to an item.

But you must be careful, as you normally want to update an item because it has changed some properties that affect rendering you need to use a custom ClusterRenderer that supports this and overrides onClusterItemRendered() and/or onClusterRendered() . Using the onBefore variants wont work because they are only called once on marker creation.

You can look at this GitHub issue GitHub issue

Since my app needs to update the clusters multiple times after the map is created, I found this workflow as the best solution to remove and add new clusters:

mGoogleMap.clear();
mClusterManager.clear(); 
//Do work to add items to cluster
mClusterManager.addItems(yourItemsList);
//Finally 
mClusterManager.cluster(); 

That should force the clusters to rerender after modifying the contents.

What worked for me was not clear() the map, because I have some other markers not attached to the cluster manager.

What worked for me is:

this.clustermanger.clearItems()
this.clustermanager.clusterMakerCollection.clear()
//and I had to force a "cluster" again, force the clustermanager to take down all markers
this.clustermanager.cluster()

You should be able to do:

val didUpdate = clusterManager?.updateItem(MyClusterItem(data))
clusterManager?.cluster()

The key here to ensure that the clusterManager does actually update the item is to override equals and hashcode in your class that extends ClusterItem, like:

fun getId(): String {
    return data.id
}
override fun equals(other: Any?): Boolean {
    return other is MyClusterItem && other.getId() == getId()
}
override fun hashCode(): Int {
    return getId().hashCode()
}

I was wondering how I could have had this problem - I've never ran into issues like this before with map nodes.

However, this was in my sample app's set-up-or-update-map logic:

        mClusterManager = new ClusterManager<>(getContext(), googleMap);
        mClusterManager.setAnimation(false);
        mClusterManager.clearItems();

I was adding nodes from a db then also some nodes from a request, there was a noticeable impact until I added a null check for the constructor

ie, this is how I should have had it:

    if (mClusterManager == null)
            mClusterManager = new ClusterManager<>(getContext(), googleMap);
        mClusterManager.setAnimation(false);
        mClusterManager.clearItems();

I must have copied and pasted this and wasted half an hour on that .. watch out!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM