Android - 谷歌地图卡住了
Posted
技术标签:
【中文标题】Android - 谷歌地图卡住了【英文标题】:Android - google maps gets stuck 【发布时间】:2021-03-19 13:01:12 【问题描述】:我正在开发一个显示谷歌地图和一堆标记的应用程序。有很多标记,所以我将它们分成较小的组并只显示那些,它们在某些范围内,具体取决于相机的当前位置。
为此,我使用GoogleMap.OnCameraIdleListener
。首先我移除监听器,进行计算和绘图,然后将监听器恢复到包含我的地图的片段:
@Override
public void onCameraIdle()
mMap.setOnCameraIdleListener(null);
clearMap();
findTheMarkersInBounds();
displayTheMarkers();
mMap.setOnCameraIdleListener(this);
这样我只绘制我需要显示的标记,并且性能比一次在地图上拥有 1000 个标记要好得多。我也画了大约相同数量的折线,但现在不是重点。
由于某些奇怪的原因,在平移和缩放地图后不再响应。不能缩放也不能平移。应用程序显示一个没有响应的对话框,我应该等待或关闭应用程序。 logcat 中不显示任何错误。我无法准确判断何时会发生这种情况。有时在第一个锅之后,有时我可以移动 2-3 分钟左右。同样的事情发生在模拟器和物理设备上。
有人经历过这样的事情吗?谢谢! 还是我以错误的方式接近这个?我还应该如何优化地图以显示大约 1000 个标记和折线。 (标记上有文字,所以不能是同一个位图,而且所有的折线可以有不同的颜色,需要可点击,所以我不能将它们组合成一条大折线)
编辑。关于我的方法的更多信息:
在从内部数据库加载所有标记位置后,我对所有标记位置进行 for 循环,并根据它们的位置将它们放置到相应的区域。它是一个二维列表数组。
我的整个区域被划分为 32x32 个较小的矩形区域。当我搜索要显示的标记时,我会确定哪个区域在视图中并仅显示位于该区域中的那些标记。 这样我就不需要遍历所有的标记。
我的方法(非常简化)如下所示:
ArrayList<MarkerObject> markersToDisplay = new ArrayList<MarkerObject>();
private void findTheMarkersInBounds()
markersToDisplay.clear();
LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
int[] regionCoordinates = getRegionCoordinates(bounds); // i, j coordinates of my regions [0..31][0..31]
markersToDisplay.addAll(subdividedMarkers[regionCoordinates[0]][regionCoordinates[1]]);
private void drawMarkers()
if ((markersToDisplay != null) && (markersToDisplay.size() > 0))
for (int i=0; i<markersToDisplay.size(); i++)
MarkerObject mo = markersToDisplay.get(i);
LatLng position = new LatLng(mo.gpsLat, mo.gpsLon);
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(createMarker(getContext(), mo.title));
GroundOverlay m = mMap.addGroundOverlay(groundOverlayOptions.image(bitmapDescriptor).position(position, 75));
m.setClickable(true);
【问题讨论】:
您使用的是:developers.google.com/maps/documentation/android-sdk/utility/… 集群技术不适合我的项目。 【参考方案1】:如果没有findTheMarkersInBounds()
和displayTheMarkers()
的源代码,很难为您提供帮助,但您似乎需要不同的方法来提高性能,例如:
如果可能的话,改进你的 findTheMarkersInBounds()
逻辑;
在单独的线程中运行findTheMarkersInBounds()
并在findTheMarkersInBounds()
搜索期间一个接一个(或一次显示10..20 个)而不是同时显示所有标记;
如果可能的话,改进你的displayTheMarkers()
,实际上可以在画布上使用自定义绘图(如this 答案)而不是创建数千个Marker
对象。
问题更新:
小改进(首先,因为它们用于 main):
将markersToDisplay
的最大大小作为构造函数参数传递:
ArrayList<MarkerObject> markersToDisplay = new ArrayList<MarkerObject>(1000);
改为for (int i=0; i<markersToDisplay.size(); i++)
使用for (MarkerObject mo: markersToDisplay)
-
不要每次都创建
LatLng position
,创建一次并存储在MarkerObject
字段中。
主要改进:
这几行是问题的根源:
BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(createMarker(getContext(), mo.title));
GroundOverlay m = mMap.addGroundOverlay(groundOverlayOptions.image(bitmapDescriptor).position(position, 75));
恕我直言,使用地面覆盖显示数千个标记是个坏主意。 Ground Overlay 用于显示默认谷歌地图的几个“用户”地图(如公园或动物园详细信息的本地计划)。在画布上使用自定义绘图,如上面的链接。但是,如果您决定使用地面叠加层 - 不要每次都重新创建它们:创建一次,将它们的引用存储在 MarkerObject
中并重复使用:
// once when marker created (just example)
mo.overlayOptions = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromBitmap(createMarker(getContext(), mo.title)))
.position(mo.position, 75))
.setClickable(true);
...
// in your drawMarkers() - just add:
...
for (MarkerObject mo: markersToDisplay)
if (mo.overlayOptions == null)
mo.overlayOptions = createOverlayOptionsForThisMarker();
mMap.addGroundOverlay(mo.overlayOptions)
但是恕我直言 - 完全摆脱成千上万的地面覆盖 - 在画布上使用自定义绘图。
【讨论】:
我更新了我的问题。添加了我的方法的源代码。我将尝试使用单独的线程来尝试这个想法。【参考方案2】:在与谷歌地图安卓技术支持进一步调查和沟通后,我们找到了解决方案。 GroundOverlay.setZIndex() 方法中存在错误。
您所要做的就是更新到最新的 API 版本。 Google Maps SDK v3.1 中不再存在该错误。
目前它处于测试阶段,但迁移非常简单。
【讨论】:
以上是关于Android - 谷歌地图卡住了的主要内容,如果未能解决你的问题,请参考以下文章