Issue on removing item from clustermanager
Asked Answered
S

5

11

In my Android application, I have to delete and re-add a cluster item in my GoogleMap, that represents my current location. But when I run this code:

clusterMng.remove(myitem);

I get this Exception:

java.lang.UnsupportedOperationException: NonHierarchicalDistanceBasedAlgorithm.remove    
not implemented.

Can someone explain to me what this means? Do I have to rewrite some methods of ClusterManager.java in the external library? Or can I simply change my algorithm?

Smallminded answered 26/2, 2014 at 17:31 Comment(0)
T
15

By default ClusterManager uses NonHierarchicalDistanceBasedAlgorithm, that doesn't implement removing elements.

Try to use GridBasedAlgorithm instead (it supports elements remove):

clusterMng.setAlgorithm(new GridBasedAlgorithm<MyClusterItem>());

Or, for better performance, wrap it with PreCachingAlgorithmDecorator, as ClusterManager does by default:

clusterMng.setAlgorithm(new PreCachingAlgorithmDecorator<MyClusterItem>(new GridBasedAlgorithm<MyClusterItem>()));
Toady answered 5/3, 2014 at 16:54 Comment(1)
This is a good solution, but wrapping the algorithm with PreCachingAlgorithmDecorator is unnecessary as it automatically does this in the setAlgorithm() method.Gonad
T
8

As @SergePopulov said, NonHierarchicalDistanceBasedAlgorithm does not implement removing elements. For those who dont want to use GridBasedAlgoritm but still needs to remove single elements from NonHierarchicalDistanceBasedAlgorithm there is another solution.

Using this link (Source) you can find source code for the NonHierarchicalDistanceBasedAlgorithm provided by developers in github.

What I did is just save the old Cluster items, clear the clusterManager and add the old items again but do not add the one that is passed through the method.

Firstly create a separate class and paste NonHierarchicalDstanceBasedAlgorithm class code.

public class CustomNonHierarchicalDistanceBasedAlgorithm<MarkerItem extends ClusterItem> implements Algorithm<MarkerItem>
{
    //copy code here
}

After that find method removeItem and replace it with this code:

@Override
public void removeItem(MarkerItem item)
{
    final Collection<QuadItem<MarkerItem>> items = new ArrayList<QuadItem<MarkerItem>>();
    final PointQuadTree<QuadItem<MarkerItem>> quadTree = new PointQuadTree<QuadItem<MarkerItem>>(0, 1, 0, 1);

    for (QuadItem<MarkerItem> temp : mItems)
    {
        if (item.getPosition() != temp.getPosition())
        {
            synchronized (quadTree)
            {
                items.add(temp);
                quadTree.add(temp);
            }
        }
    }

    clearItems();

    for (QuadItem<MarkerItem> temp : items)
    {
        synchronized (mQuadTree)
        {
            mItems.add(temp);
            mQuadTree.add(temp);
        }
    }
}

After that go where your ClusterManager is created and paste code below containing your class name:

clusterManager.setAlgorithm(new CustomNonHierarchicalDistanceBasedAlgorithm<MarkerItem>());

Where your MarkerItem is your class which implemented ClusterItem. And it should now work.

Don't forget to recluster your ClusterManager after you remove the item by running:

clusterManager.cluster();
Tenebrae answered 20/11, 2014 at 14:28 Comment(1)
I am getting MarkerItems cannot be resolved to a type error messageSucking
B
8

Here is how I did it:

@Override
public void removeItem(T item) {
    final QuadItem<T> quadItem = new QuadItem<T>(item);
    synchronized (mQuadTree) {
        mItems.remove(quadItem);
        mQuadTree.remove(quadItem);
    }
}

I also implemented equals() and hashCode() in QuadItem as it is recommended in the TODO of the NonHierarchicalDistanceBasedAlgorithm source code:

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (!(o instanceof QuadItem)) {
        return false;
    }

    QuadItem quadItem = (QuadItem) o;

    return mClusterItem.equals(quadItem.mClusterItem);

}

@Override
public int hashCode() {
    return mClusterItem.hashCode();
}

Finally, I implemented equals() and hashCode() in my ClusterItem's descendant class.

Bradley answered 26/11, 2014 at 16:4 Comment(6)
confirmed, that this solution works! Performance wise it seems good. Can handle over 1k markersFerity
@Viachaslau Tysianchuk , how did you managed to modify the NonHierarchicalDistanceBasedAlgorithm.QuadItem to implements those methods? Did you have to use the library as a module?Mismate
@Mismate I've copied the full source code of android-maps-utils into my project because I needed to make several other changes. For this case copying just the NonHierarchicalDistanceBasedAlgorithm could be enough.Bradley
This isn't working for me. I downloaded the NonHierarchical class and changed removeItem method, and implemented the equals & hashcode methods. Then, in my 'CustomItem extends ClusterItem' class i just overrode equals & hashcode. Any suggestions? Thank you!Escorial
@Escorial Can't suggest much without looking at your code. Maybe check if your implementation of hashCode() follows the rules from docs.oracle.com/javase/7/docs/api/java/lang/…. Wrong implementation of hashCode() could cause bugs while working with hashmaps and hashsets.Bradley
I'm getting java.lang.NullPointerException: Attempt to invoke interface method 'boolean java.util.List.remove(java.lang.Object)' on a null object reference custom_classes.CustomNonHierarchicalDistanceBasedAlgorithm.removeItem(CustomNonHierarchicalDistanceBasedAlgorithm.java:74) BUT mItems cannot be null??? EDIT: Ah that was because I called clearItems before removeItem. BUT now I get ConcurrentModificationException...Psychological
S
1

After updating android-maps-utils to 0.5

clusterManager.remove(item); will never throw an UnsupportedOperationException("NonHierarchicalDistanceBasedAlgorithm.remove not implemented")

Refer this thread

Sorrells answered 3/7, 2018 at 12:40 Comment(0)
S
0

I have found removeItem(T item) in the source code of ClusterManager.java Tested, it works Link to source code https://github.com/googlemaps/android-maps-utils/blob/master/library/src/com/google/maps/android/clustering/ClusterManager.java

Strait answered 8/6, 2017 at 9:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.