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&lt;MarkerObject&gt; markersToDisplay = new ArrayList&lt;MarkerObject&gt;(1000);

    改为for (int i=0; i&lt;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 - 谷歌地图卡住了的主要内容,如果未能解决你的问题,请参考以下文章

android-谷歌地图停止工作

谷歌地图只显示空白瓷砖android

Android 中的 Google 地图部署或发布问题?

在 Android 应用程序中加载谷歌地图太慢了

有啥方法可以在 Flutter for Web 中添加谷歌地图?

使用片段的谷歌地图