Недавно я разработал мобильное приложение html5. Приложение представляло собой единую страницу, на которой события изменения хеш-функции навигации заменяли всю DOM. Одним из разделов приложения была карта Google с использованием API v3. Перед тем, как div карты будет удален из DOM, я хочу удалить все обработчики / прослушиватели событий и освободить как можно больше памяти, поскольку пользователь не может снова вернуться в этот раздел.
Как лучше всего уничтожить экземпляр карты?
javascript
google-maps-api-3
Чад Киллингсворт
источник
источник
Ответы:
Я добавляю второй ответ на этот вопрос, потому что я не хочу убирать то, что у нас было в последующих комментариях к моему предыдущему ответу.
Но недавно я наткнулся на некоторую информацию, которая напрямую касается вашего вопроса, и поэтому я хотел поделиться. Я не знаю, знаете ли вы об этом, но во время рабочего дня Google Maps API Office Hours 9 мая 2012 г. Крис Бродфут и Люк Маэ из Google обсуждали именно этот вопрос из stackoverflow. Если вы установите воспроизведение видео на 12:50, это раздел, в котором они обсуждают ваш вопрос.
По сути, они признают, что это ошибка, но также добавляют, что на самом деле они не поддерживают варианты использования, которые включают создание / уничтожение последовательных экземпляров карты. Они настоятельно рекомендуют создать единственный экземпляр карты и повторно использовать его в любом подобном сценарии. Они также говорят об установке для карты значения NULL и явном удалении прослушивателей событий. Вы выразили обеспокоенность по поводу прослушивателей событий, я подумал, что достаточно просто установить для карты значение null, но похоже, что ваши опасения обоснованы, потому что они конкретно упоминают прослушиватели событий. Они также рекомендовали полностью удалить DIV, который также содержит карту.
В любом случае, просто хотел передать это и убедиться, что он включен в обсуждение stackoverflow, и надеюсь, что это поможет вам и другим -
источник
Официальный ответ является не нужно. Экземпляры карт в одностраничном приложении следует использовать повторно, а не уничтожать, а затем воссоздавать.
Для некоторых одностраничных приложений это может означать изменение архитектуры решения таким образом, чтобы после создания карты она могла быть скрыта или отключена от 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. Если вам нужно перезагрузить систему, вы можете использовать mapInstancesPool.reset (). Он сбросит счетчик на 0, сохраняя при этом все существующие экземпляры в пуле для повторного использования. В моем приложении мне нужно было удалить все карты сразу и создать новый набор карт, поэтому нет функции для переработки конкретного экземпляра карты: ваш пробег может отличаться. Чтобы удалить карты с экрана, я использую функцию отсоединения jQuery, которая не разрушает контейнер карты.
Используя эту систему и используя
google.maps.event.clearInstanceListeners(window); google.maps.event.clearInstanceListeners(document);
и бег
google.maps.event.clearInstanceListeners(divReference[0]); divReference.detach()
(где divReference - это объект jQuery div, возвращаемый из пула экземпляров) на каждом удаляемом div мне удалось сохранить более или менее стабильное использование памяти Chrome, в отличие от его увеличения каждый раз, когда я удаляю карты и добавляю новые.
источник
Я бы предложил удалить содержимое div карты и использовать
delete
переменную, содержащую ссылку на карту, и, возможно, явноdelete
указать какие-либо прослушиватели событий.Однако есть признанная ошибка , и это может не сработать.
источник
delete
добавляет много (см. Stackoverflow.com/q/742623/1314132 ), но это действительно не повредит. В конце концов, все сводится к вопросу: есть ли ссылки на объект? Если да, сборщиком мусора не будет.GUnload()
должна удалить все внутренние ссылки API.delete
это не совсем исправление. Они должны исправить большую проблему, чтобы сделать ссылки недоступными, работали должным образом, или добавить новую функцию, обеспечивающую описанные вами функцииGUnload()
.delete
и очисткаinnerHTML
не полностью очищает память. К сожалению, это не высокоприоритетная ошибка.Поскольку Google не предоставляет gunload () для api v3, лучше используйте iframe в html и назначьте map.html в качестве источника для этого iframe. после использования сделайте src нулевым. Это определенно освободит память, потребляемую картой.
источник
Когда вы удалите
div
, это приведет к удалению панели дисплея, и карта исчезнет. Чтобы удалить экземпляр карты, просто убедитесь, что для вашей ссылки на карту установлено значениеnull
и что для всех ссылок на другие части карты установлено значениеnull
. В этот момент сборка мусора JavaScript позаботится об очистке, как описано в разделе : Как сборка мусора работает в JavaScript? .источник
null
, но и любые ссылки на что-либо еще. Таким образом, если ссылка на маркер установлена в значениеnull
, что делает его недоступным , нет возможности связаться с прослушивателем событий. Он все еще может быть подключен к карте, но карта недоступна, поэтому это просто большой кусок памяти, который по существу стал бесхозным. Это то же самое, что и установкаArray.length = 0
; если нет других ссылок на элементы, они просто образуют группу осиротевшей памяти, подходящую для сборки мусора.Я предполагаю, что вы говорите
addEventListener
. Когда вы удаляете элементы DOM, некоторые браузеры пропускают эти события и не удаляют их. Вот почему jQuery при удалении элемента выполняет несколько действий:removeEventListener
. Это означает, что он хранит массив со слушателями событий, которые он добавил в этот элемент.onclick
,onblur
и т. Д.), Которые используютсяdelete
в элементе DOM, когдаaddEventListener
он недоступен (тем не менее, у него есть массив, в котором он хранит добавленные события).null
избежать утечек памяти IE 6/7/8.источник
removeEventListener
или вdelete
зависимости от типа события.