2011-10-05 13 views
10

En mi aplicación Google Maps v3, estoy creando marcadores y colocándolos en el mapa. Para cada uno, estoy agregando un detector de eventos en 'clic' para que pueda mostrar una ventana de información cuando un usuario hace clic en ellos.En Google Maps v3, ¿eliminar un marcador de la memoria mata automáticamente a los oyentes?

Mantengo mis marcadores en una matriz de Javascript y uso .setMap() para mostrarlos/ocultarlos en el mapa. Hay algunos casos en que un usuario quiere eliminarlos del mapa. En este caso, hago marker.setMap (null) y luego elimino el marcador de mi matriz.

¿Se recomienda también mantener una variedad de detectores de eventos en los marcadores para poder eliminarlos cuando elimine el marcador? ¿O el receptor de eventos se eliminará de la memoria cuando se escuche? ¿Se elimina el objeto de la memoria?

Desde el punto de vista del usuario final, no creo que sea importante hacer esto, pero tengo curiosidad por saber si el detector de eventos todavía está en la memoria en alguna parte aunque elimine el marcador. Me gustaría ser tan ordenado como sea posible.

Respuesta

12

No estoy seguro de si se eliminan los oyentes, pero supongo que no. Supongo que, dado que el oyente todavía está escuchando, aunque ya no tenga una referencia al objeto, el oyente lo hace, por lo que permanecerá en la memoria. No es necesario para mantener una referencia para el oyente, puede llamar

google.maps.event.clearInstanceListeners(marker); 

para borrar todos los oyentes antes de eliminarlo de su matriz.

1

Por lo que puedo decir, los oyentes se eliminan de la memoria.

En teoría, esto se debe probablemente a que los oyentes no escuchan activamente como tal: Google Maps solo los almacena en la función relevante y luego pregunta qué función tienen los oyentes cuando se dispara un evento.

Prácticamente, me encontré con una prueba, y estos son los resultados:

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

uso de memoria en JS es absurdamente difícil de rastrear, en parte (sospecho) debido al recolector de basura automático. Para obtener estos resultados, utilicé el administrador de tareas integrado de Chrome, y después de cada paso importante del experimento hice un ciclo de un gran trozo de memoria dentro y luego fuera de uso para forzar la mano del recolector de basura.

Una curiosidad aquí es que cuando la pestaña 1 pierde el punto, pierde aproximadamente 2000K de memoria, mientras que cuando la pestaña 2 baja el punto, gana 77K (un cambio insignificante dada la volatilidad del uso de la memoria). Sospecho que esto se debe a que la pestaña 1 arroja un punto con 20000 oyentes conectados, mientras que la pestaña 2 deja un punto vacío.

Aquí está la fuente que utilicé. No estoy proporcionando un enlace violín, violín, porque sólo hace un seguimiento del uso de memoria aún más difícil:/

html (inserte su propia clave de 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); 
} 
Cuestiones relacionadas