【问题标题】:Google Maps Utility: how to get all markers from ClusterManager<?>?Google Maps Utility:如何从 ClusterManager<?> 中获取所有标记?
【发布时间】:2014-03-17 08:12:32
【问题描述】:

对不起我的英语

我尝试了ClusterManager&lt;?&gt;.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 的那一刻,但没有在地图上放置标记,稍后会做(可能在后台线程中)。如果是这样,那我怎样才能抓住那一刻?

【问题讨论】:

  • 您找到解决问题的方法了吗?
  • clusterManager.getClusterMarkerCollection().getMarkers();仅当标记处于缩放级别时才返回标记,以便我们可以在地图中看到它们
  • 由于 ClusterManager 方法 cluster() 创建并调用 ClusterManager.ClusterTask() AsyncTask,因此您在调用 cluster() 后尝试正确获取标记是错误的。似乎当 ClusterManager.ClusterTask 完成时,它会调用 ClusterRenderer 对象上的 onClustersChanged() 方法。

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


【解决方案1】:

我会给你一个很好的解决方法。首先,我将介绍一些背景。然后,我会告诉你修改代码的非常简单的方法。

背景:我们先从库代码看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。算法是存储您的项目的位置。现在来看一下 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();
    

这会返回项目而不是 Marker 对象,但我相信这是您需要的。

【讨论】:

  • 很好的解决方案!你有一个错字:应该是'clusterManagerAlgorithm = new NonHierarchicalDistanceBasedAlgorithm'(你在 NonHierarchicalDistanceBasedAlgorithm 中缺少第一个'N')
  • 只是说 - 原始的 setAlgorithm 方法不可避免地用缓存算法包装你的算法,这在某些情况下可能会很困难,因为这种包装算法也会自动获取集群以获得越来越低的缩放级别,这意味着一个 getClusters(缩放)调用 = 3 次调用。我知道他们是线程化的,但只是说在同样的情况下这可能是不需要的。
【解决方案2】:

覆盖其中之一:

onBeforeClusterItemRendered

onBeforeClusterRendered

onClusterRendered

onClusterItemRendered

就像

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

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

【讨论】:

    【解决方案3】:

    @Ethan 解决方案有效。另一个技巧是使用Reflection API 来访问ClusterManager 类的mAlgorithm(正如Ethan mAlgorithm 提到的,你的项目存储在哪里)字段。

    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&lt;T&gt; mAlgorithm),需要在业务逻辑中进行更改。

    【讨论】:

    • 这个解决方案对我来说很棒
    【解决方案4】:

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

    我和你一样尝试过

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

    试试吧

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

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

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

    【讨论】:

    • clusterManager.getClusterMarkerCollection().getMarkers();仅当标记处于缩放级别时才返回标记,以便我们可以在地图中看到它们
    • 是的,你是对的,我发现它只返回出现的标记,而不是集群中的标记
    【解决方案5】:

    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中获取marker或者cluster item了

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

    它并没有为您提供完整的标记集合,但如果您仍然需要它,您应该使用循环来创建它。

    【讨论】:

    • 这是迄今为止唯一对我有用的东西,但它并没有返回所有标记。然而,一个简单的循环可以满足 OP 的要求。干杯
    【解决方案6】:
    你应该尝试这样的事情:
    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 已定义。
    这对我尝试在集群内实现过滤很有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-13
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2011-02-04
      • 1970-01-01
      • 2015-08-01
      • 1970-01-01
      相关资源
      最近更新 更多