Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android, callback when map clustering is completed

I am using Google Maps and its clustering utility in my app. Clustering itself is working fine, but I have issue, when I try to deal with configuration changes.

This is my case:

  1. User sees a map on a screen, which is a fragment.
  2. When clustering is completed, markers on map appear. User can interact with markers.
  3. When user selects a marker, it is highlighted and BottomSheet is expanded to display.

If user rotates screen (i.e. configuration change happens), I save what marker was selected using onSaveInstanceState (actually I do not save marker itself, but only a link to related List entry like ID). Then, I want to restore that user selection that was before configuration change.

Clustering itself is executed like this:

clusterManager.clearItems();
clusterManager.addItems(eventManager.getEventList());
clusterManager.cluster(); 

This code is executed, when data is received from server. When clustering is executed, all markers, obviously, are recreated as well. So in order to highlight previous user selection (previous marker), I must know WHEN clustering utility finishes its operation. By that time I am sure that I can safely use such functions like:

clusterManager.getRenderer()).getMarker(<param>)

and

clusterManager.getRenderer()).getClusterItem(<param>)

otherwise, these will return null sometimes, if clustering task is not completed yet.

However, I cannot find a reasonable way, how to get a response from clustering utility (i.e. ClusterManager), when clustering is completed. I think I need to update this standard clustering code:

 /**
     * Runs the clustering algorithm in a background thread, then re-paints when results come back.
     */
    private class ClusterTask extends AsyncTask<Float, Void, Set<? extends Cluster<T>>> {
        @Override
        protected Set<? extends Cluster<T>> doInBackground(Float... zoom) {
            mAlgorithmLock.readLock().lock();
            try {
                return mAlgorithm.getClusters(zoom[0]);
            } finally {
                mAlgorithmLock.readLock().unlock();
            }
        }

        @Override
        protected void onPostExecute(Set<? extends Cluster<T>> clusters) {
            mRenderer.onClustersChanged(clusters);
        }
    }

I think, that onPostExecute should provide a response not to Renderer only, but to a user of ClusterManager (like my fragment) that clustering is done. But I do not want to modify standard code.

Is there a better way how to handle this case?

like image 463
rofl Avatar asked Sep 28 '16 09:09

rofl


1 Answers

You are going about this the wrong way.

You should implement:

class YourClusterItemRenderer extends DefaultClusterRenderer<YourClusterItem>

and set it to ClusterManager as renderer like this:

mClusterManager.setRenderer(new YourClusterItemRenderer(...));

Override YourClusterItemRenderer's methods onBeforeClusterItemRendered and onBeforeClusterRendered and there you can change what each marker looks like according to your logic as per parameters from your server.

So when ClusterManager finishes rendering all your markers already look like you want them according to user state etc.

like image 98
EZDsIt Avatar answered Nov 15 '22 21:11

EZDsIt