В Google Maps v3 удаляет ли маркер из памяти автоматически убивать всех слушателей?

В моем приложении Google Maps v3 я создаю маркеры и помещаю их на карту. Для каждого я добавляю прослушиватель событий на 'click', поэтому я могу показать информационное окно, когда пользователь нажимает на них.

Я сохраняю свои маркеры в массиве javascript и использую .setMap(), чтобы показать/скрыть их на карте. Есть некоторые случаи, когда пользователь хочет, чтобы они были удалены с карты. В этом случае я делаю marker.setMap(null), а затем удаляю маркер из своего массива.

Рекомендуется ли хранить массив прослушивателей событий на маркерах, чтобы я мог удалить их при удалении маркера? Или прослушиватель событий удаляется из памяти при прослушивании - объект удаляется из памяти?

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

Ответ 1

Я не знаю точно, если слушатели удалены, но я думаю, что нет. Я предполагаю, что, поскольку слушатель все еще прослушивает, хотя у вас больше нет ссылки на объект, слушатель делает это, поэтому он останется в памяти. Вам не нужно сохранять ссылку на слушателя, вы можете позвонить

google.maps.event.clearInstanceListeners(marker);

чтобы очистить всех слушателей, прежде чем удалять их из массива.

Ответ 2

Насколько я могу судить, слушатели удаляются из памяти.

Теоретически, это, вероятно, потому, что слушатели не активно слушают как таковые - Карты Google хранят их только в соответствующей функции, а затем спрашивают, какую функцию прослушивают слушатели при запуске события.

Практически, я провел тест, и это результаты:

Tabs 1 and 2 create a point with 20000 listeners, and track the listeners.
Tab 3 creates a point with 20000 listeners, but doesn't track them.
Stage 1 is after they've got the listeners.
Stage 2 is after they've dropped something (tab 1: point, 2: listeners, 3: point)
Stage 3 is after they've dropped the other (tab 1: listeners, 2: point, 3: no change (listeners dropped implicitly at stage 2) )
Tab     PID     Memory (live, K) at stage...
                1       2       3
1       4643    18194   16026    8265
2       4659    18174    8155    8227
3       4676    17750    8152    8202

Использование памяти в JS абсурдно трудно отслеживать, частично (я подозреваю) из-за автоматического сборщика мусора. Чтобы получить эти результаты, я использовал хром, встроенный в диспетчер задач, и после того, как каждый крупный шаг эксперимента переместил большой кусок памяти в и затем вышел из употребления, чтобы заставить руку сборщика мусора.

Любое любопытство здесь заключается в том, что, когда табль 1 понижает точку, она теряет около 2000 КБ памяти, а когда вкладка 2 понижает точку, она получает 77 Кб (незначительное изменение, учитывая волатильность использования памяти). Я подозреваю, что это связано с тем, что вкладка 1 сбрасывает точку с подключением 20000 слушателей, в то время как вкладка 2 падает на гору.

Вот источник, который я использовал. Я не предоставляю ссылку на скрипку, потому что скрипка просто делает отслеживание использования памяти еще сложнее:/

html (введите свой собственный ключ API):

<!DOCTYPE html>
<html>
        <head>
                <style type="text/css">
                        html, body {height: 100%; width: 100%;}
                        #map {width: 100%; height: 80%;}
                </style>
        </head>
        <body>
<h1>Welcome to MapLand, home of a single map.</h1>
<div id="map"></div>
<button onclick="addPts(true);">add points (store listeners)</button>
<button onclick="addPts(false);">add points (don't store listeners)</button>
--------
<button onclick="deletePts();">delete points</button>
<button onclick="deleteLs();">delete listeners</button>
-------- 
<button onclick="checkListenerVar();">check listener var</button>
<button onclick="cycleLargeChunk();">cycle large chunk</button>
        </body>
        <script src="test2.js"></script>
        <script async src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAorBo-zMFJo9viqdv3pkuhMyg5hytpbaQ&callback=initMap"></script>
</html>

JS (test2.js):

var uluru = {lat: -25.363, lng: 131.044};
var map;
function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
                zoom: 4,
                center: uluru
        });
}
var ptLat = uluru.lat, ptLng = uluru.lng;
var pts = []; // points
var ls = []; // listeners
var listenerVar;
function addPts(storeLs) {
        var m = new google.maps.Marker({
                position: {lat: ptLat, lng: ptLng},
                map: map
        });
        ptLng += 1;
        if (ptLng > uluru.lng + 20) {
                ptLng = uluru.lng;
                ptLat += 1;
        }
        pts.push(m);
        for (var i = 50000; i > 0; i--) {
                var l = google.maps.event.addListener(m, 'click', function () {listenerVar = i;});
                if (storeLs) ls.push(l);
        }
}
function deletePts() {
        for (var i = pts.length-1; i >= 0; i--) pts[i].setMap(null);
        pts = [];
        ptLat = uluru.lat;
        ptLng = uluru.lng;
}
function deleteLs() {
        for (var i = ls.length-1; i >= 0; i--) ls[i].remove();
        ls = [];
}
function checkListenerVar() {
        alert("Listener var is " + listenerVar + ", but is being reset to -1.");
        listenerVar = -1;
}
function cycleLargeChunk() {
        var l = [0];
        for (var i = 0; i < 26; i++) {
                l = l.concat(l);
        }
        //Force the environment to hang on to l for at least a second.
        setTimeout(function () {console.log(l.length);}, 1000);
}