Каков правильный способ уничтожить экземпляр карты?

Недавно я разработал мобильное приложение html5. Приложение представляло собой единую страницу, в которой события изменения хэша навигации заменяли всю DOM. Одним из разделов приложения была карта Google, использующая API v3. Перед удалением карты из DOM я хочу удалить любые обработчики/прослушиватели событий и освободить как можно больше памяти, так как пользователь может не вернуться в этот раздел еще раз.

Каков наилучший способ уничтожить экземпляр карты?

Ответ 1

официальный ответ - это не так. Экземпляры карт в одностраничном приложении должны быть повторно использованы и не уничтожены, а затем воссозданы.

Для некоторых приложений с одной страницей это может означать повторное архивирование решения таким образом, что после создания карты он может быть скрыт или отключен от DOM, но он никогда не уничтожается/не воссоздается.

Ответ 2

Я добавляю второй ответ на этот вопрос, потому что я не хочу удалять назад и вперед, если бы мы следили за моим предыдущим ответом.

Но я недавно натолкнулся на некоторую информацию, которая напрямую затрагивает ваш вопрос, и поэтому я хотел бы поделиться. Я не знаю, знаете ли вы об этом, но во время Google Office API Часы 9 мая 2012 года Крис Бродфут и Люк Маэ из Google обсудили этот вопрос из stackoverflow. Если вы установите воспроизведение видео на 12:50, это раздел, где они обсуждают ваш вопрос.

По сути, они признают, что это ошибка, но также добавляют, что они действительно не поддерживают варианты использования, связанные с созданием/уничтожением последовательных экземпляров карты. Они настоятельно рекомендуют создавать один экземпляр карты и повторно использовать ее в любом сценарии такого рода. Они также говорят о настройке карты на нуль и явно удалении прослушивателей событий. Вы выразили озабоченность слушателями событий, я думал, что достаточно просто установить карту в null, но похоже, что ваши проблемы действительны, потому что они упоминают прослушиватели событий. Они также рекомендовали полностью удалить DIV, который также содержит карту.

Во всяком случае, просто хотел передать это и убедиться, что он включен в обсуждение stackoverflow и надеюсь, что он поможет вам и другим -

Ответ 3

Поскольку, по-видимому, вы действительно не можете уничтожить экземпляры карты, способ уменьшить эту проблему, если

  • вам нужно отобразить сразу несколько карт на веб-сайте.
  • количество карт может меняться при взаимодействии с пользователем
  • карты должны быть скрыты и повторно показаны вместе с другими компонентами (т.е. они не отображаются в фиксированной позиции в DOM)

хранит пул экземпляров карты. Пул хранит следы используемых экземпляров, и когда запрашивается новый экземпляр, он проверяет, свободен ли какой-либо из доступных экземпляров карты: если он есть, он вернет существующий, если это не так, он создаст новый экземпляр карты и верните его, добавив его в пул. Таким образом, у вас будет только максимальное количество экземпляров, равное максимальному количеству карт, которые вы когда-либо показывали на экране. Я использую этот код (он требует jQuery):

var mapInstancesPool = {
 pool: [],
 used: 0,
 getInstance: function(options){
    if(mapInstancesPool.used >= mapInstancesPool.pool.length){
        mapInstancesPool.used++;
        mapInstancesPool.pool.push (mapInstancesPool.createNewInstance(options));
    } else { 
        mapInstancesPool.used++;
    }
    return mapInstancesPool.pool[mapInstancesPool.used-1];
 },
 reset: function(){
    mapInstancesPool.used = 0;
 },
 createNewInstance: function(options){
    var div = $("<div></div>").addClass("myDivClassHereForStyling");
    var map =   new google.maps.Map(div[0], options);
    return {
        map: map,
        div: div
    }
 }
}

Вы передаете ему исходные параметры карты (в соответствии со вторым аргументом конструктора google.maps.Map), и он возвращает оба экземпляра карты (на которые вы можете вызывать функции, относящиеся к google.maps.Map), и контейнер, который вы можете использовать, используя класс "myDivClassHereForStyling", и вы можете динамически присоединяться к DOM. Если вам нужна reset система, вы можете использовать mapInstancesPool.reset(). Он будет reset счетчиком 0, сохраняя все существующие экземпляры в пуле для повторного использования. В моем приложении мне нужно было сразу удалить все карты и создать новый набор карт, поэтому нет возможности перерабатывать конкретный экземпляр карты: ваш пробег может отличаться. Чтобы удалить карты с экрана, я использую jQuery detach, который не уничтожает контейнер карты.

Используя эту систему и используя

google.maps.event.clearInstanceListeners(window);
google.maps.event.clearInstanceListeners(document);

и работает

google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()

(где divReference - это объект div jQuery, возвращаемый из пула экземпляров) на каждом div, который я удаляю, мне удалось сохранить использование памяти в Chrome более или менее стабильным, а не увеличивать каждый раз, когда я удаляю карты и добавляю новые.

Ответ 4

Я бы предложил удалить содержимое div div и использовать delete для переменной, содержащей ссылку на карту, и, возможно, явно delete для любых прослушивателей событий.

Существует признанная ошибка, но это может не сработать.

Ответ 5

Поскольку google не предоставляет gunload() для api v3, лучше использовать iframe в html и назначать map.html в качестве источника для этого iframe. после использования сделайте src равным нулю. Это определенно освободит память, потребляемую картой.

Ответ 6

При удалении div, который удаляет панель дисплея, и карта исчезнет. Чтобы удалить экземпляр карты, просто убедитесь, что ваша ссылка на карту установлена ​​на null и что любые ссылки на другие части карты установлены на null. В этот момент сборка мусора JavaScript позаботится об очистке, как описано в: Как работает сборка мусора в JavaScript?.

Ответ 7

Думаю, вы говорите о addEventListener. Когда вы удаляете элементы DOM, некоторые браузеры пропускают эти события и не удаляют их. Вот почему jQuery выполняет несколько операций при удалении элемента:

  • Он удаляет события, когда он может использовать removeEventListener. Это означает, что он сохраняет массив с прослушивателями событий, добавленными в этот элемент.
  • Он удаляет атрибуты событий (onclick, onblur и т.д.) с помощью delete в элементе DOM, когда addEventListener недоступен (все же у него есть массив, в котором он хранит добавленные события).
  • Он устанавливает элемент null, чтобы избежать утечек памяти IE 6/7/8.
  • Затем он удаляет элемент.