Подтвердить что ты не робот

75 маркеров на карте → утечки памяти → OutOfMemoryException

У меня проблема с отображением примерно 80 маркеров на карте Google. Я использую 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 память не освобождается.

Кто-нибудь знает, неправильно ли я добавляю маркеры или сталкиваюсь с проблемой в реализации 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 В соответствии с этим вопросом необходимо исправить, но я сам его не тестировал.

4b9b3361

Ответ 1

Да, вы столкнулись с очень классической и распространенной проблемой, которая поражает множество разработчиков Android... угрожающего OOM. Проблема возникает, когда вы не полностью очищаете свои старые чертежи при обновлении или ротации. Чтобы исправить это, вам действительно нужно перебирать маркеры до mMap.clear и устанавливать их в null и, возможно, запрашивать (вы не можете заставить) сборку мусора, вызывая System.gc().

Ответ 2

Здесь один из подходов, который вы можете использовать в качестве возможного решения для возможной проблемы API... обнаружите вращение устройства и удалите объект MarketOptions, установив его в null... затем повторно заполните его вашими маркерами.

Ответ 3

Всякий раз, когда у меня возникают проблемы с утечкой памяти в моих приложениях, я просматриваю следующий сценарий

  • Загрузите приложение
  • Выполните операцию, которая подозревается в утечке памяти (желательно более одного раза, поэтому ее легче анализировать)
  • Завершите приложение (нажимая назад, пока он не вернется на главный экран)
  • Анализ дампа памяти

Шаги, которые я использую для моего анализа, это

  • Открытая гистограмма
  • Поиск имени моего пакета
  • Проверьте, нет ли ссылок, которые не должны быть

Если есть утечки, и вы повторяли операцию утечки несколько раз, вы увидите несколько экземпляров фрагментов, действий, представлений и т.д. Чтобы определить виновника утечки:

  • Щелкните правой кнопкой мыши на просочившемся объекте → Список объектов → с входящей ссылкой
  • Выберите одну из входящих ссылок, щелкните правой кнопкой мыши → Путь к корням GC → исключить WeakReferences
  • Откройте уровни стека, пока не найдете ссылку. Если единственный путь ведет к финализатору, вы слишком глубоко вырыты. Если это было неубедительно, попробуйте еще один просочившийся объект, повторите шаги.

Извините, что это не точная наука, но это приведет к подсказкам, которые позволят вам легче идентифицировать пропущенный код.