Android Google Map addMarker() очень медленный при добавлении 400 маркеров
Спасибо, что нашли время, чтобы прочитать это.
Я опубликовал приложение в магазине Google Play около месяца назад (08/29/14), и это не проблема с тем же количеством маркеров. На этой неделе я заметил, что когда я пошел в свое приложение, чтобы загрузить 400 маркеров на карту заняло около 10-20 секунд на моей Galaxy S5 и что есть маленький круг в середине значков маркеров карты по умолчанию. До этого карта загружалась менее чем за секунду. Я не обновлял или не менял свое приложение. Я предполагаю, что Google обновил API Карт Google, и изменение сделало его намного медленнее, чтобы загрузить маркеры? Это случилось с кем-то еще? Кто-нибудь еще имеет информацию об этом?
Мое приложение доступно бесплатно в Play Маркете. Вы можете найти руководство NYS Canal Guide, чтобы найти его, если хотите посмотреть, как медленно он загружается.
Этот метод вызывается в onCreateView() фрагмента карты после инициализации карты:
private void addExistingMarkersToMap(){
log("Adding existing markers to the map. poiAdapter size = " + poiAdapter.getCount());
Marker marker;
MarkerOptions markerOptions;
for(MapMarker mapMarker : poiAdapter){
if(markersNotFilteredOut(mapMarker)){
markerOptions = mapMarker.getMarkerOptions();
if(markerOptions != null && mapMarker != null){
marker = mMap.addMarker(markerOptions);
mapMarker.setMarker(marker);
}
}
}
}
Это метод getMarkerOptions() в классе MapMarker:
public MarkerOptions getMarkerOptions() {
return new MarkerOptions()
.title(name)
.position(new LatLng(lat, lng))
.snippet(bodyOfWater + ", mile " + mile)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
}
Полный исходный код находится здесь: github.com/olearyj234/NYS-Canal-Guide
EDIT:
** Чтобы быть конкретным, единственная медленная часть - это загрузка маркеров при инициализации карты (так же при переключении с одной вкладки навигации и обратно на вкладку карты). Это не медленно при перемещении карты или чего-либо еще.
Вот несколько журналов, которые появляются:
Пока экран замораживается на несколько секунд (5-15), поскольку он загружает маркеры, этот журнал создается очень быстро. Идентификатор растрового изображения продолжает увеличиваться на единицу и пока маркеры загружаются, он производит около 400 из этих журналов. Это показывает, что это проблема, связанная с загрузкой растровых изображений маркера на экране. Я использую растровое изображение маркера по умолчанию.
10-01 15:45:07.222: D/skia(32108): GFXPNG PNG bitmap created width:16 height:32 bitmap id is 414
Этот журнал создается, когда приложение завершает загрузку всех маркеров на карту.
10-01 15:51:09.402: I/Choreographer(8353): Skipped 1130 frames! The application may be doing too much work on its main thread.
Этот журнал создается 14 раз, когда приложение завершает загрузку всех маркеров на карту.
10-01 15:59:13.882: I/dalvikvm-heap(8353): Grow heap (frag case) to 40.668MB for 4194320-byte allocation
ИЗМЕНИТЬ 2:
Я просто проверил, сколько времени потребуется для определенных строк кода. Я использовал System.currentTimeMillis();
, чтобы получить время. В методе addExistingMarkersToMap()
это линия, которая заняла много времени: marker = mMap.addMarker(markerOptions);
При добавлении всех 400 маркеров для каждого маркера потребовалось в среднем 54 мс. Минимальное время составляло 34 мс, а максимальное - 114 мс.
Если вам нужна дополнительная информация, которую я должен предоставить, сообщите мне в комментарии.
Спасибо!
Ответы
Ответ 1
Это, по-видимому, новая проблема, появившаяся в Google Maps API v2 (выглядит как одно из обновлений Play Services 6), см. # 7174 для получения дополнительной информации (и пожалуйста, звездочка).
Из информации, предоставленной в проблеме, проблема, похоже, специфична для использования маркера по умолчанию с оттенком, например:
BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)
Есть некоторые обходные пути. Проще всего не указывать оттенок (если все ваши маркеры красные допустимы):
BitmapDescriptorFactory.defaultMarker()
Или использовать пользовательские чертежи:
BitmapDescriptorFactory.fromResource(R.drawable.map_marker)
Я вижу замедление в 2000 раз при использовании маркера по умолчанию с оттенком. На данный момент я собираюсь использовать пользовательские чертежи в качестве решения.
Ответ 2
Я понимаю, что каждый раз, когда вы рисуете маркер, он отправляет операции рисования в пул потоков в фоновом режиме, пока он возвращает маркер. Легко перегружать процессор, наводя запрос слишком быстро.
Используйте обработчик из основного петлителя и отправляйте задержку с возрастающими интервалами, чтобы развернуть операции, как в приведенном ниже коде.
Handler handler = new Handler(Looper.getMainLooper());
int x = 0;
long DELAY = 10;
for(MapMarker mapMarker : poiAdapter){
if(markersNotFilteredOut(mapMarker)){
markerOptions = mapMarker.getMarkerOptions();
if(markerOptions != null && mapMarker != null){
handler.postDelayed(
new Runnable() {
@Override
public void run() {
marker = mMap.addMarker(markerOptions);
mapMarker.setMarker(marker);
}
}, (DELAY * (long)x++));
}
}
}