Google Maps Utility:如何从ClusterManager <! - ? - >获取所有标记?

时间:2014-03-17 08:12:33

标签: android google-maps-android-api-2 marker markerclusterer

抱歉我的英文

我尝试了ClusterManager<?>.getMarkerCollection().getMarkers()方法,但它返回空集合。

我在我的应用Google Maps Utility Library中使用。每次在屏幕旋转之后,我创建AsynkTask并在后台线程中从数据库中读取数据并将项目添加到ClusterManager

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

AsyncTask完成其工作(即在主线程中)时,我试图从ClusterManager获取所有标记:

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

ClusterManager返回空集合。

可能正好在我致电getMarkers()ClusterManager尚未在地图上放置标记并稍后执行此操作(可能在后台线程中)。如果是这样,那我怎么能抓住那一刻?

6 个答案:

答案 0 :(得分:12)

我会给你一个很好的解决方法。首先,我将给出一些背景知识。然后,我将告诉您修改代码的简单方法。

背景:让我们首先看一下库代码中ClusterManager.addItem的实现:

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

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

}

如您所见,当您调用clusterManager.addItem时,ClusterManager会调用this.mAlgorithm.addItem。 mAlgorithm是存储项目的地方。现在让我们看一下ClusterManager的默认构造函数:

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

mAlgorithm被实例化为包含NonHierarchicalDistanceBasedAlgorithm的PreCachingAlgorithmDecorator。不幸的是,由于mAlgorithm被声明为私有,我们无法访问正在添加到算法中的项目。但是,很高兴有一个简单的解决方法!我们只是使用ClusterManager.setAlgorithm实例化mAlgorithm。这允许我们访问算法类。

替代方法:这是您的代码,其中插入了变通方法。

  1. 将此声明与您的类变量一起使用:

    private Algorithm<Post> clusterManagerAlgorithm;
    
  2. 在您实例化ClusterManager的地方,然后立即将其放入:

     // Instantiate the cluster manager algorithm as is done in the ClusterManager
     clusterManagerAlgorithm = new NonHierarchicalDistanceBasedAlgorithm();
    
     // Set this local algorithm in clusterManager
     clusterManager.setAlgorithm(clusterManagerAlgorithm);
    
  3. 您可以将用于将项目插入群集的代码完全相同。

  4. 如果要访问插入的项目,只需使用算法而不是ClusterManager:

    Collection<ClusterItemImpl> items = clusterManagerAlgorithm.getItems();
    
  5. 这会返回项目而不是Marker对象,但我相信这是你需要的。

答案 1 :(得分:3)

覆盖其中一个:

onBeforeClusterItemRendered

onBeforeClusterRendered

onClusterRendered

onClusterItemRendered

就像

一样
 @Override
    protected void onClusterRendered(Cluster<MyItem> cluster, Marker marker) {
        super.onClusterRendered(cluster, marker);
    }

cluster.getItems()将返回集群中的标记

答案 2 :(得分:1)

我有同样的问题来获得所有标记或至少获得标记的数量。我想我找到了获得标记的解决方案。

我试过像你一样

markers = clusterManager.getMarkerCollection().getMarkers(); 

尝试改为

markers = clusterManager.getClusterMarkerCollection().getMarkers();

此行返回了我的标记,但我不确定这是否是您/我们想要的结果。我需要检查一下。

注意 我会把我的答案写成评论,但我没有足够的观点......

答案 3 :(得分:1)

@Ethan解决方案有效。另一个黑客是使用Reflection API来访问mAlgorithm(正如Ethan mAlgorithm所提到的那样存储项目的位置)ClusterManager类的字段。

try {
            Field field = mClusterManager.getClass().getDeclaredField("mAlgorithm");
            field.setAccessible(true);
            Object mAlgorithm = field.get(mClusterManager);
            List<MapItems> markers = new ArrayList<>(((Algorithm<MapItems>)mAlgorithm).getItems());
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

注意: - 将来如果字段名称有任何变化(即private Algorithm<T> mAlgorithm),则需要在业务逻辑中进行更改。

答案 4 :(得分:0)

Ethan的回答很好,但是您仍然无法获得标记。 您需要创建自定义ClusterRenderer并使用它来获取Marker或ClusterItem。

   override fun onMapReady(map: GoogleMap) {
        clusterManager = ClusterManager(this, map)
        clusterRenderer = CustomClusterRenderer(this@ATMActivity, map, this)
        clusterManager.renderer = clusterRenderer
   }

   inner class CustomClusterRenderer(
        context: Context,
        map: GoogleMap,
        clusterManager: ClusterManager<CustomClusterItem>
) : DefaultClusterRenderer<CustomClusterItem>(context, map, clusterManager) 

然后您可以从clusterRenderer获取标记或群集项

clusterRenderer.getMarker(clusterItem) // returns Marker object for selected cluster item 
clusterRenderer.getClusterItem(marker) // returns ClusterItem object for selected marker

它不能为您提供完整的标记集合,但是如果您仍然真正需要它,则应该使用循环来创建它。

答案 5 :(得分:0)

您应该尝试这样的事情:
private MyItem mitemfilter;
renderer = new MyClusterManagerRender(this, googleMap, clusterManager);
clusterManager.setRenderer(renderer);

addItems();

    private void addItems() {
       clusterManager.addItem(mitemfilter=new  MyItem (19.641936, -99.132669, "food", "Villa Esmeralda, 54910 Fuentes del Valle, Méx.",R.drawable.ic_camaron));
        }

    private void foodfilter(){
    renderer.getMarker(mitemfilter).setVisible(false);
    
    }
假设您的模型Myitem已定义。
这对我尝试在集群内部实施过滤的工作。