Android Open Source - downtown Cluster Manager






From Project

Back to project page downtown.

License

The source code is released under:

GNU General Public License

If you think the Android project downtown listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.google.maps.android.clustering;
//from   w w  w. java2  s  .  c o  m
import android.content.Context;
import android.os.AsyncTask;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.Marker;
import com.google.maps.android.MarkerManager;
import com.google.maps.android.clustering.algo.Algorithm;
import com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm;
import com.google.maps.android.clustering.algo.PreCachingAlgorithmDecorator;
import com.google.maps.android.clustering.view.ClusterRenderer;
import com.google.maps.android.clustering.view.DefaultClusterRenderer;

import java.util.Collection;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Groups many items on a map based on zoom level.
 * <p/>
 * ClusterManager should be added to the map as an: <ul> <li>{@link com.google.android.gms.maps.GoogleMap.OnCameraChangeListener}</li>
 * <li>{@link com.google.android.gms.maps.GoogleMap.OnMarkerClickListener}</li> </ul>
 */
public class ClusterManager<T extends ClusterItem> implements GoogleMap.OnCameraChangeListener, GoogleMap.OnMarkerClickListener, GoogleMap.OnInfoWindowClickListener {
    private static final String TAG = ClusterManager.class.getName();

    private final MarkerManager mMarkerManager;
    private final MarkerManager.Collection mMarkers;
    private final MarkerManager.Collection mClusterMarkers;

    private Algorithm<T> mAlgorithm;
    private final ReadWriteLock mAlgorithmLock = new ReentrantReadWriteLock();
    private ClusterRenderer<T> mRenderer;

    private GoogleMap mMap;
    private CameraPosition mPreviousCameraPosition;
    private ClusterTask mClusterTask;
    private final ReadWriteLock mClusterTaskLock = new ReentrantReadWriteLock();

    private OnClusterItemClickListener<T> mOnClusterItemClickListener;
    private OnClusterInfoWindowClickListener<T> mOnClusterInfoWindowClickListener;
    private OnClusterItemInfoWindowClickListener<T> mOnClusterItemInfoWindowClickListener;
    private OnClusterClickListener<T> mOnClusterClickListener;

    public ClusterManager(Context context, GoogleMap map) {
        this(context, map, new MarkerManager(map));
    }

    public ClusterManager(Context context, GoogleMap map, MarkerManager markerManager) {
        mMap = map;
        mMarkerManager = markerManager;
        mClusterMarkers = markerManager.newCollection();
        mMarkers = markerManager.newCollection();
        mRenderer = new DefaultClusterRenderer<T>(context, map, this);
        mAlgorithm = new PreCachingAlgorithmDecorator<T>(new NonHierarchicalDistanceBasedAlgorithm<T>());
        mClusterTask = new ClusterTask();
        mRenderer.onAdd();
    }

    public MarkerManager.Collection getMarkerCollection() {
        return mMarkers;
    }

    public MarkerManager.Collection getClusterMarkerCollection() {
        return mClusterMarkers;
    }

    public MarkerManager getMarkerManager() {
        return mMarkerManager;
    }

    public void setRenderer(ClusterRenderer<T> view) {
        mRenderer.setOnClusterClickListener(null);
        mRenderer.setOnClusterItemClickListener(null);
        mClusterMarkers.clear();
        mMarkers.clear();
        mRenderer.onRemove();
        mRenderer = view;
        mRenderer.onAdd();
        mRenderer.setOnClusterClickListener(mOnClusterClickListener);
        mRenderer.setOnClusterInfoWindowClickListener(mOnClusterInfoWindowClickListener);
        mRenderer.setOnClusterItemClickListener(mOnClusterItemClickListener);
        mRenderer.setOnClusterItemInfoWindowClickListener(mOnClusterItemInfoWindowClickListener);
        cluster();
    }

    public void setAlgorithm(Algorithm<T> algorithm) {
        mAlgorithmLock.writeLock().lock();
        try {
            if (mAlgorithm != null) {
                algorithm.addItems(mAlgorithm.getItems());
            }
            mAlgorithm = new PreCachingAlgorithmDecorator<T>(algorithm);
        } finally {
            mAlgorithmLock.writeLock().unlock();
        }
        cluster();
    }

    public void clearItems() {
        mAlgorithmLock.writeLock().lock();
        try {
            mAlgorithm.clearItems();
        } finally {
            mAlgorithmLock.writeLock().unlock();
        }
    }

    public void addItems(Collection<T> items) {
        mAlgorithmLock.writeLock().lock();
        try {
            mAlgorithm.addItems(items);
        } finally {
            mAlgorithmLock.writeLock().unlock();
        }

    }

    public void addItem(T myItem) {
        mAlgorithmLock.writeLock().lock();
        try {
            mAlgorithm.addItem(myItem);
        } finally {
            mAlgorithmLock.writeLock().unlock();
        }
    }

    public void removeItem(T item) {
        mAlgorithmLock.writeLock().lock();
        try {
            mAlgorithm.removeItem(item);
        } finally {
            mAlgorithmLock.writeLock().unlock();
        }
    }

    /**
     * Force a re-cluster. You may want to call this after adding new item(s).
     */
    public void cluster() {
        mClusterTaskLock.writeLock().lock();
        try {
            // Attempt to cancel the in-flight request.
            mClusterTask.cancel(true);
            mClusterTask = new ClusterTask();
            mClusterTask.execute(mMap.getCameraPosition().zoom);
        } finally {
            mClusterTaskLock.writeLock().unlock();
        }
    }

    /**
     * Might re-cluster.
     *
     * @param cameraPosition
     */
    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
        if (mRenderer instanceof GoogleMap.OnCameraChangeListener) {
            ((GoogleMap.OnCameraChangeListener) mRenderer).onCameraChange(cameraPosition);
        }

        // Don't re-compute clusters if the map has just been panned/tilted/rotated.
        CameraPosition position = mMap.getCameraPosition();
        if (mPreviousCameraPosition != null && mPreviousCameraPosition.zoom == position.zoom) {
            return;
        }
        mPreviousCameraPosition = mMap.getCameraPosition();

        cluster();
    }

    @Override
    public boolean onMarkerClick(Marker marker) {
        return getMarkerManager().onMarkerClick(marker);
    }

    @Override
    public void onInfoWindowClick(Marker marker) {
        getMarkerManager().onInfoWindowClick(marker);
    }

    /**
     * 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);
        }
    }

    /**
     * Sets a callback that's invoked when a Cluster is tapped. Note: For this listener to function,
     * the ClusterManager must be added as a click listener to the map.
     */
    public void setOnClusterClickListener(OnClusterClickListener<T> listener) {
        mOnClusterClickListener = listener;
        mRenderer.setOnClusterClickListener(listener);
    }

    /**
     * Sets a callback that's invoked when a Cluster is tapped. Note: For this listener to function,
     * the ClusterManager must be added as a info window click listener to the map.
     */
    public void setOnClusterInfoWindowClickListener(OnClusterInfoWindowClickListener<T> listener) {
        mOnClusterInfoWindowClickListener = listener;
        mRenderer.setOnClusterInfoWindowClickListener(listener);
    }

    /**
     * Sets a callback that's invoked when an individual ClusterItem is tapped. Note: For this
     * listener to function, the ClusterManager must be added as a click listener to the map.
     */
    public void setOnClusterItemClickListener(OnClusterItemClickListener<T> listener) {
        mOnClusterItemClickListener = listener;
        mRenderer.setOnClusterItemClickListener(listener);
    }

    /**
     * Sets a callback that's invoked when an individual ClusterItem's Info Window is tapped. Note: For this
     * listener to function, the ClusterManager must be added as a info window click listener to the map.
     */
    public void setOnClusterItemInfoWindowClickListener(OnClusterItemInfoWindowClickListener<T> listener) {
        mOnClusterItemInfoWindowClickListener = listener;
        mRenderer.setOnClusterItemInfoWindowClickListener(listener);
    }

    /**
     * Called when a Cluster is clicked.
     */
    public interface OnClusterClickListener<T extends ClusterItem> {
        public boolean onClusterClick(Cluster<T> cluster);
    }

    /**
     * Called when a Cluster's Info Window is clicked.
     */
    public interface OnClusterInfoWindowClickListener<T extends ClusterItem> {
        public void onClusterInfoWindowClick(Cluster<T> cluster);
    }

    /**
     * Called when an individual ClusterItem is clicked.
     */
    public interface OnClusterItemClickListener<T extends ClusterItem> {
        public boolean onClusterItemClick(T item);
    }

    /**
     * Called when an individual ClusterItem's Info Window is clicked.
     */
    public interface OnClusterItemInfoWindowClickListener<T extends ClusterItem> {
        public void onClusterItemInfoWindowClick(T item);
    }
}




Java Source Code List

com.google.maps.android.BuildConfig.java
com.google.maps.android.BuildConfig.java
com.google.maps.android.MarkerManager.java
com.google.maps.android.MathUtil.java
com.google.maps.android.PolyUtil.java
com.google.maps.android.SphericalUtil.java
com.google.maps.android.clustering.ClusterItem.java
com.google.maps.android.clustering.ClusterManager.java
com.google.maps.android.clustering.Cluster.java
com.google.maps.android.clustering.algo.Algorithm.java
com.google.maps.android.clustering.algo.GridBasedAlgorithm.java
com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm.java
com.google.maps.android.clustering.algo.PreCachingAlgorithmDecorator.java
com.google.maps.android.clustering.algo.StaticCluster.java
com.google.maps.android.clustering.view.ClusterRenderer.java
com.google.maps.android.clustering.view.DefaultClusterRenderer.java
com.google.maps.android.geometry.Bounds.java
com.google.maps.android.geometry.Point.java
com.google.maps.android.projection.Point.java
com.google.maps.android.projection.SphericalMercatorProjection.java
com.google.maps.android.quadtree.PointQuadTree.java
com.google.maps.android.ui.BubbleIconFactory.java
com.google.maps.android.ui.IconGenerator.java
com.google.maps.android.ui.RotationLayout.java
com.google.maps.android.ui.SquareTextView.java
com.sothree.slidinguppanel.SlidingUpPanelLayout.java
com.sothree.slidinguppanel.library.BuildConfig.java
com.sothree.slidinguppanel.library.BuildConfig.java
org.dklisiaris.downtown.Addresses.java
org.dklisiaris.downtown.BuildConfig.java
org.dklisiaris.downtown.FavsActivity.java
org.dklisiaris.downtown.GlobalData.java
org.dklisiaris.downtown.Intro.java
org.dklisiaris.downtown.MainActivity.java
org.dklisiaris.downtown.Manifest.java
org.dklisiaris.downtown.MapActivity.java
org.dklisiaris.downtown.MoreActivity.java
org.dklisiaris.downtown.Products.java
org.dklisiaris.downtown.SearchActivity.java
org.dklisiaris.downtown.Search.java
org.dklisiaris.downtown.SingleListItem.java
org.dklisiaris.downtown.Subcategories.java
org.dklisiaris.downtown.SubcatsAndFilters.java
org.dklisiaris.downtown.Tabs.java
org.dklisiaris.downtown.TestActivity.java
org.dklisiaris.downtown.WebViewActivity.java
org.dklisiaris.downtown.Websites.java
org.dklisiaris.downtown.actionbar.ActionBar.java
org.dklisiaris.downtown.actionbar.ScrollingTextView.java
org.dklisiaris.downtown.adapters.AddressFilterAdapter.java
org.dklisiaris.downtown.adapters.CustomAdapter.java
org.dklisiaris.downtown.adapters.CustomStringAdapter.java
org.dklisiaris.downtown.adapters.CustomSuggestionsAdapter.java
org.dklisiaris.downtown.adapters.MultiSelectionAdapter.java
org.dklisiaris.downtown.adapters.SubcatsAdapter.java
org.dklisiaris.downtown.db.Banner.java
org.dklisiaris.downtown.db.Category.java
org.dklisiaris.downtown.db.Company.java
org.dklisiaris.downtown.db.DBHandler.java
org.dklisiaris.downtown.db.DBInterface.java
org.dklisiaris.downtown.db.Image.java
org.dklisiaris.downtown.db.InitData.java
org.dklisiaris.downtown.db.Keyword.java
org.dklisiaris.downtown.db.Mapping.java
org.dklisiaris.downtown.db.Product.java
org.dklisiaris.downtown.db.QueryBuilder.java
org.dklisiaris.downtown.downloader.DownloadTask.java
org.dklisiaris.downtown.downloader.NotificationHelper.java
org.dklisiaris.downtown.helper.AccessAssets.java
org.dklisiaris.downtown.helper.AlertDialogManager.java
org.dklisiaris.downtown.helper.ConnectionDetector.java
org.dklisiaris.downtown.helper.FileCache.java
org.dklisiaris.downtown.helper.ImageLoader.java
org.dklisiaris.downtown.helper.InfoHelper.java
org.dklisiaris.downtown.helper.KeyboardUtil.java
org.dklisiaris.downtown.helper.MemoryCache.java
org.dklisiaris.downtown.helper.ShareHelper.java
org.dklisiaris.downtown.helper.UpdateConfirmDialog.java
org.dklisiaris.downtown.helper.UpdateHelper.java
org.dklisiaris.downtown.helper.Utils.java
org.dklisiaris.downtown.helper.XMLParser.java
org.dklisiaris.downtown.maps.AbstractMapActivity.java
org.dklisiaris.downtown.maps.CompanyMarker.java
org.dklisiaris.downtown.maps.DirectionsInfo.java
org.dklisiaris.downtown.maps.GMapV2Direction.java
org.dklisiaris.downtown.maps.Nearby.java
org.dklisiaris.downtown.maps.PopupAdapter.java
org.dklisiaris.downtown.providers.KeywordContract.java
org.dklisiaris.downtown.providers.KeywordProvider.java
org.dklisiaris.downtown.widgets.AspectRatioImageView.java
org.dklisiaris.downtown.widgets.CheckableRelativeLayout.java
org.dklisiaris.downtown.widgets.CustomScrollView.java
org.dklisiaris.downtown.widgets.FlipAnimator.java
org.dklisiaris.downtown.widgets.InertCheckBox.java
org.dklisiaris.downtown.widgets.MultiSpinner.java