地图上的75个标记 - >内存泄漏 - > OutOfMemoryException异常

时间:2013-01-06 19:53:06

标签: android maps out-of-memory google-maps-android-api-2

我在Google地图上绘制大约80个标记时出现问题。我正在使用Google Maps Android API v2。

标记的图标是动态的(时间变化)。将标记添加到地图后,无法更改图标。因此,我必须删除所有标记并再次添加所有标记。

mMap.clear();
for (int i = 0; i < teams.length(); i++) {
    team = teams.get(i);
    point = new LatLng(tema.getLatitude(), team.getLongitude());

    MarkerOptions marker = new MarkerOptions().position(point).title(name).icon(BitmapDescriptorFactory.fromResource(team.getMarkerId())));
        mMap.addMarker(marker);
}

多次执行此代码后(每分钟刷新一次),我得到一个OutOfMemoryExpcetion。

当使用较大的标记图标时,OutOfMemoryException会更快地抛出,因此我认为内存问题与图标位图有关,而该图位图未正确回收。

我还想到,当将设备的旋转从横向更改为portait并返回时,会增加使用的堆内存。在GC之后,内存不会被释放。

有人知道我是否错误地添加了标记,还是我在Map API实现中遇到了问题?


我尝试使用Google Map示例应用程序重现错误。在android-sdk/extras/google/google_play_services/samples/maps/src/com/example/mapdemo/MarkerDemoActivity.java中,可以找到标记演示。加快测试速度我增加了创建的标记数量。

int numMarkersInRainbow = 12;

更改为

int numMarkersInRainbow = 100;

现在启动演示应用程序,选择标记演示并将设备的旋转从纵向切换到横向并返回几次。

初始堆:

Heap size   Allocated  Free      %Used    #Objects
11,543 BM   9,898 MB   1,645 MB  85,75%   65.982

在几个方向更改后堆积:

Heap size   Allocated  Free      %Used    #Objects
15,652 MB   11,337 MB  4,316 MB  72,43%   76.984

在更改一些方向后堆积:

Heap size   Allocated  Free      %Used    #Objects
21,312 MB   16,411 MB  4,901 MB  77,00%   111.350

最终结果将是OutOfMemoryExcpetion。

堆转储显示一些可能的堆泄漏:https://www.box.com/s/rsy0k22dcp267se2g1fy

完整堆转储:https://www.box.com/s/6lyv2p6rlc0njqxw5zgu

更新: 这似乎与Android Maps V2中的内存泄漏问题有关。见https://code.google.com/p/gmaps-api-issues/issues/detail?id=4766 根据问题应该修复,但我没有自己测试。

3 个答案:

答案 0 :(得分:1)

是的,你面临着一个非常经典和常见的问题,困扰着很多Android开发者......威胁性的OOM。如果您没有在更新或轮换时完全清理旧的drawable,则会出现此问题。要修复你,你应该在mMap.clear之前迭代你的标记并将它们设置为null,并且可能通过调用System.gc()来请求(你不能强制它)垃圾收集。

答案 1 :(得分:0)

您可以采用以下方法解决可能的API问题:检测设备轮换并通过将其设置为null来删除MarketOptions对象...然后使用您的标记重新填充它。

答案 2 :(得分:0)

每当我的应用程序出现内存泄漏问题时,我都会遇到以下情况

  1. 加载应用
  2. 执行怀疑泄漏内存的操作(最好多次,以便以后更容易分析)
  3. 完成应用程序(按下直到返回主屏幕)
  4. 分析内存转储
  5. 我用于分析的步骤是

    1. 打开直方图
    2. 搜索我的包名称
    3. 检查是否有任何不应该
    4. 的引用

      如果有泄漏并且您多次重复泄漏操作,您将看到多个碎片,活动,视图等实例。为了识别泄漏的罪魁祸首:

      1. 右键单击泄漏的对象 - &gt;列出对象 - &gt;传入参考
      2. 选择一个传入参考,右键单击 - &gt; GC根的路径 - &gt;排除WeakReferences
      3. 打开堆栈级别,直到找到引用。如果唯一的路径通向终结器,那么你挖的太深了。如果它不确定,请尝试另一个泄漏的对象,重复步骤。
      4. 很抱歉,这不是一门精确的科学,但它会提供一些提示,使您能够更轻松地识别漏洞代码。