Android 谷歌地图实用程序:如何从ClusterManager获取所有标记<>;?

Android 谷歌地图实用程序:如何从ClusterManager获取所有标记<>;?,android,google-maps-android-api-2,marker,markerclusterer,Android,Google Maps Android Api 2,Marker,Markerclusterer,对不起,我的英语不好 我尝试了ClusterManager.getMarkerCollection().getMarkers()方法,但它返回空集合 我在我的应用程序中使用谷歌地图实用程序库。每次屏幕旋转后,我都会创建AsynkTask,并在后台线程中从数据库读取数据,并将项目添加到ClusterManager: cursor.moveToFirst(); while (!cursor.isAfterLast()) { SomeData row = readSomeDataRow(cur

对不起,我的英语不好

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

我在我的应用程序
中使用谷歌地图实用程序库
。每次屏幕旋转后,我都会创建
AsynkTask
,并在后台线程中从数据库读取数据,并将项目添加到
ClusterManager

cursor.moveToFirst();
while (!cursor.isAfterLast()) {
    SomeData row = readSomeDataRow(cursor);
    clusterManager.addItem(new ClusterItemImpl(row));
    cursor.moveToNext();
}
clusterManager.cluster();
// cluster manager returns empty collection  \|/
markers = clusterManager.getMarkerCollection().getMarkers(); 
AsyncTask
完成其工作(即在主线程中)时,我尝试从
ClusterManager
获取所有标记:

cursor.moveToFirst();
while (!cursor.isAfterLast()) {
    SomeData row = readSomeDataRow(cursor);
    clusterManager.addItem(new ClusterItemImpl(row));
    cursor.moveToNext();
}
clusterManager.cluster();
// cluster manager returns empty collection  \|/
markers = clusterManager.getMarkerCollection().getMarkers(); 
但是
ClusterManager
返回空集合


可能是在我调用
getMarkers()
ClusterManager的时候,但没有在地图上放置标记,稍后会执行(可能在后台线程中)。如果是这样的话,那么我怎样才能抓住那一刻呢?

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

我试着像你一样

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

markers = clusterManager.getClusterMarkerCollection().getMarkers();
此行返回了标记,但我不确定这是否是您/我们想要的结果。我需要检查一下

注意 我会将我的答案作为评论来写,但我没有足够的观点。

覆盖其中一个:

onBeforeClusterItemRendered

onBeforeClusterRendered

无群集的

OnClusterItem

就像

 @Override
    protected void onClusterRendered(Cluster<MyItem> cluster, Marker marker) {
        super.onClusterRendered(cluster, marker);
    }
@覆盖
受保护的void onClusterRendered(群集、标记){
super.onClusterRendered(集群、标记);
}

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

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

背景:让我们首先从库代码中了解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());
    ...        
}
Collection<ClusterItemImpl> items = clusterManagerAlgorithm.getItems();
mAlgorithm被实例化为包含非HierarchicalDistanceBaseDalGorithm的PreachingGalGorithmDecorator。不幸的是,由于mAlgorithm被声明为私有,我们无法访问添加到算法中的项。然而,令人高兴的是,有一个简单的解决办法!我们只是使用ClusterManager.setAlgorithm实例化mAlgorithm。这允许我们访问算法类

变通方法:这是插入了变通方法的代码

  • 将此声明与类变量放在一起:

    private Algorithm<Post> clusterManagerAlgorithm;
    
  • 您可以保持将项目插入集群的代码完全相同

  • 当您想要访问插入的项目时,只需使用与ClusterManager相反的算法:

    public ClusterManager(Context context, GoogleMap map, MarkerManager markerManager) {
        ...
        this.mAlgorithm = new PreCachingAlgorithmDecorator(new  NonHierarchicalDistanceBasedAlgorithm());
        ...        
    }
    
    Collection<ClusterItemImpl> items = clusterManagerAlgorithm.getItems();
    
    Collection items=clusterManagerAlgorithm.getItems();
    

  • 这将返回项目而不是标记对象,但我相信这是您所需要的。

    @Ethan solution有效。另一种方法是使用
    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();
            }
    
    试试看{
    Field Field=mClusterManager.getClass().getDeclaredField(“mAlgorithm”);
    字段。setAccessible(true);
    对象mAlgorithm=field.get(mClusterManager);
    列表标记=新的ArrayList(((算法)mAlgorithm.getItems());
    }捕获(无此字段例外){
    e、 printStackTrace();
    }捕获(非法访问例外e){
    e、 printStackTrace();
    }
    

    注意:-将来如果字段名有任何更改(即
    私有算法mAlgorithm
    ),则需要在业务逻辑中进行更改。

    Ethan的回答很好,但您仍然无法使用它获取标记。 您需要创建自定义ClusterRenderer并使用它来获取标记或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) 
    

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

    您应该尝试以下方法:
    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);
        
        }
    
    A确认您的模型Myitem已定义。

    这对于我尝试在集群内实现过滤非常有用。您找到解决问题的方法了吗?clusterManager.getClusterMarkerCollection().getMarkers();仅当标记处于缩放级别时才返回标记,以便我们可以在地图中看到它们。由于ClusterManager方法cluster()创建并调用ClusterManager.ClusterTask()AsyncTask,因此在调用cluster()后尝试正确获取标记是错误的。似乎当ClusterManager.ClusterTask完成时,它会调用ClusterRenderer对象.ClusterManager.getClusterMarkerCollection().getMarkers()上的方法OnClusterChanged();仅当标记处于缩放级别时才返回标记,以便我们可以在地图中看到它们是的,您是对的,我发现它只返回出现的标记,而不返回clustersGreat解决方案中的标记!您有一个输入错误:应该是'clusterManagerAlgorithm=new Non-HierarchicalDistanceBasedAlgorithm'(您缺少Non-HierarchicalDistanceBasedAlgorithm中的第一个'N'),只是说-原始的setAlgorithm方法不可避免地用缓存算法包装您的算法,在某些情况下,这可能会很困难,因为这种包装算法也会自动为较低和较高的缩放级别获取集群,这意味着一个getClusters(zoom)调用=3个调用。我知道它们是线程化的,但是在同样的情况下,仅仅说这可能是不需要的。这个解决方案对meThis非常好,这是到目前为止唯一对我有效的方法,但是它并没有返回所有标记。然而,一个简单的循环可以满足OP的要求。干杯