Каков правильный способ уничтожить экземпляр карты?
Недавно я разработал мобильное приложение 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.
- Затем он удаляет элемент.