抱歉我的英文
我尝试了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
尚未在地图上放置标记并稍后执行此操作(可能在后台线程中)。如果是这样,那我怎么能抓住那一刻?
答案 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。这允许我们访问算法类。
替代方法:这是您的代码,其中插入了变通方法。
将此声明与您的类变量一起使用:
private Algorithm<Post> clusterManagerAlgorithm;
在您实例化ClusterManager的地方,然后立即将其放入:
// Instantiate the cluster manager algorithm as is done in the ClusterManager
clusterManagerAlgorithm = new NonHierarchicalDistanceBasedAlgorithm();
// Set this local algorithm in clusterManager
clusterManager.setAlgorithm(clusterManagerAlgorithm);
您可以将用于将项目插入群集的代码完全相同。
如果要访问插入的项目,只需使用算法而不是ClusterManager:
Collection<ClusterItemImpl> items = clusterManagerAlgorithm.getItems();
这会返回项目而不是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已定义。