Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Maps Utility: how to get all markers from ClusterManager<?>?

Sorry for my English

I tried the ClusterManager<?>.getMarkerCollection().getMarkers() method but it returns empty collection.

I use in my app Google Maps Utility Library. Every time after a screen rotation I create AsynkTask and in background thread read data from DB and add items to ClusterManager:

cursor.moveToFirst();
while (!cursor.isAfterLast()) {
    SomeData row = readSomeDataRow(cursor);
    clusterManager.addItem(new ClusterItemImpl(row));
    cursor.moveToNext();
}

When the AsyncTask finished its work (i.e. in main thread) I tried to get all markers from the ClusterManager:

clusterManager.cluster();
// cluster manager returns empty collection  \|/
markers = clusterManager.getMarkerCollection().getMarkers(); 

but the ClusterManager returns empty collection.

May be at the moment when I call getMarkers() the ClusterManager yet doesn't place markers on map and will do it a bit later (may be in background thread). If so, then how can I catch that moment?

like image 415
Leonid Semyonov Avatar asked Mar 17 '14 08:03

Leonid Semyonov


People also ask

What is marker clustering?

Marker clusters is the concept of sampling the data values into larger blocks in order to ease readability and increase performance. It is a simple solution to display a large number of markers on a map, or a chart. The number on a cluster shows how many markers it contains.

What is clustering in Google Maps?

The way marker clustering works is that it provides a summary marker that gives you an idea of what's “below” at closer zoom levels. Typically, you click a clustered marker to automatically zoom into an area with either additional clustered markers or individual markers.


1 Answers

I will give you a nice workaround. First, I will give some background. Then, I will tell you the very simple method for modifying your code.

BACKGROUND: Let's first look at the implementation of ClusterManager.addItem from the library code:

public void addItem(T myItem) {
    this.mAlgorithmLock.writeLock().lock();

    try {
        this.mAlgorithm.addItem(myItem);
    } finally {
        this.mAlgorithmLock.writeLock().unlock();
    }

}

As you can see, when you call clusterManager.addItem, the ClusterManager then calls this.mAlgorithm.addItem. mAlgorithm is where your item is stored. Let's now look at the default constructor of ClusterManager:

public ClusterManager(Context context, GoogleMap map, MarkerManager markerManager) {
    ...
    this.mAlgorithm = new PreCachingAlgorithmDecorator(new  NonHierarchicalDistanceBasedAlgorithm());
    ...        
}

mAlgorithm is instantiated as a PreCachingAlgorithmDecorator containing a NonHierarchicalDistanceBasedAlgorithm. Unfortunately, since mAlgorithm is declared private, we don't have access to the items which are being added to the algorithm. However, there is happily an easy workaround! We simply instantiate mAlgorithm using ClusterManager.setAlgorithm. This allows us access to the algorithm class.

WORKAROUND: Here is your code with the workaround inserted.

  1. Put this declaration with your class variables:

    private Algorithm<Post> clusterManagerAlgorithm;
    
  2. In the place where you instantiate your ClusterManager, put this immediately afterwards:

     // Instantiate the cluster manager algorithm as is done in the ClusterManager
     clusterManagerAlgorithm = new NonHierarchicalDistanceBasedAlgorithm();
    
     // Set this local algorithm in clusterManager
     clusterManager.setAlgorithm(clusterManagerAlgorithm);
    
  3. You can leave your code for inserting items into the cluster exactly the same.

  4. When you want to get access to the items inserted, you simply use the algorithm as opposed to the ClusterManager:

    Collection<ClusterItemImpl> items = clusterManagerAlgorithm.getItems();
    

This returns the items instead of the Marker objects, but I believe it is what you need.

like image 100
Ethan Avatar answered Oct 05 '22 17:10

Ethan