J'ai récemment développé une application mobile html5. L'application était une page unique où les événements de changement de hachage de navigation remplaçaient l'intégralité du DOM. Une section de l'application était une carte Google Map utilisant API v3. Avant que le div de la carte ne soit supprimé du DOM, je souhaite supprimer tout gestionnaire d'événement/écouteur et libérer autant de mémoire que possible, car l'utilisateur ne pourra plus jamais revenir à cette section.
Quel est le meilleur moyen de détruire une instance de carte?
Le réponse officielle est que vous ne le faites pas. Les instances de carte dans une application à une seule page doivent être réutilisées et non détruites puis recréées.
Pour certaines applications à une seule page, cela peut impliquer une nouvelle architecture de la solution, de sorte qu'une fois créée, une carte peut être masquée ou déconnectée du DOM, mais elle n'est jamais détruite ni recréée.
J'ajoute une deuxième réponse à cette question, car je ne veux pas supprimer les allers et retours que nous avions par le biais des commentaires de suivi de ma réponse précédente.
Mais je suis récemment tombé sur des informations qui répondent directement à votre question et je voulais donc les partager. Je ne sais pas si vous êtes au courant de cela, mais lors du Google Maps API Heures de bureau du 9 mai 2012 Vidéo , Chris Broadfoot et Luke Mahe de Google ont discuté de cette question de stackoverflow. Si vous définissez la lecture vidéo sur 12:50, c'est la section où ils discutent de votre question.
Ils reconnaissent essentiellement qu'il s'agit d'un bogue, mais ajoutent qu'ils ne prennent pas en charge les cas d'utilisation impliquant la création/la destruction d'instances de carte successives. Ils recommandent vivement de créer une seule instance de la carte et de la réutiliser dans n'importe quel scénario de ce type. Ils parlent également de la définition de la carte sur null et de la suppression explicite des écouteurs d'événements. Vous avez exprimé des préoccupations à propos des écouteurs d'événements. Je pensais que le fait de définir la carte sur null suffirait, mais il semble que vos préoccupations soient valides, car elles font spécifiquement référence aux écouteurs d'événements. Ils ont également recommandé de supprimer complètement la DIV qui contient la carte.
Quoi qu'il en soit, je voulais simplement transmettre ceci et m'assurer qu'il est inclus dans la discussion sur la superposition et espérer que cela vous aidera, à vous-même et aux autres.
Étant donné qu'apparemment, vous ne pouvez pas vraiment détruire les instances de carte, un moyen de réduire ce problème si
conserve un pool d'instances de mappage . Le pool conserve une trace des instances utilisées et, lorsqu'une nouvelle instance lui est demandée, il vérifie si l'une des instances de mappe disponibles est libre: si c'est le cas, elle renverra une instance existante si ce n’est pas le cas, il créera une nouvelle instance de carte et la retournera en l’ajoutant au pool. Ainsi, vous n'aurez qu'un nombre maximal d'instances égal au nombre maximal de cartes que vous affichez simultanément à l'écran . J'utilise ce code (il nécessite 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
}
}
}
Vous lui transmettez les options de la carte de départ (conformément au deuxième argument du constructeur de google.maps.Map) et renvoie à la fois l'instance de la carte (sur laquelle vous pouvez appeler des fonctions appartenant à google.maps.Map) et le conteneur, qui vous pouvez styler en utilisant la classe "myDivClassHereForStyling", et vous pouvez ajouter un dinamically au DOM . Si vous devez réinitialiser le système, vous pouvez utiliser mapInstancesPool.reset (). Il remettra le compteur à 0 tout en conservant toutes les instances existantes dans le pool pour pouvoir les réutiliser ..__ Dans mon application, je devais supprimer toutes les cartes en même temps et créer un nouvel ensemble de cartes. exemple: votre kilométrage peut varier ... Pour supprimer les cartes de l'écran, j'utilise le détachement de jQuery, qui ne détruit pas le conteneur de la carte.
En utilisant ce système et en utilisant
google.maps.event.clearInstanceListeners(window);
google.maps.event.clearInstanceListeners(document);
et courir
google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()
(où divReference est l’objet jQuery de la div retourné par le pool d’instances). les uns.
J'aurais suggéré de supprimer le contenu de la carte div et d'utiliser delete
sur la variable contenant la référence à la carte, et probablement explicitement delete
ing les écouteurs d'événements.
Il y a un bug reconnu , cependant, et cela risque de ne pas fonctionner.
Comme google ne fournit pas gunload () pour api v3, mieux utiliser iframe en html et assigner map.html comme source à cette iframe après utilisation, faire src comme null. Cela va certainement libérer la mémoire consommée par la carte.
Lorsque vous supprimez la div
, le panneau d’affichage est supprimé et la carte disparaît. Pour supprimer l'instance de carte, assurez-vous que votre référence à la carte est définie sur null
et que toutes les références à d'autres parties de la carte sont définies à null
. À ce stade, la récupération de mémoire JavaScript se chargera du nettoyage, comme indiqué dans: Comment fonctionne la récupération de place en JavaScript? .
Je suppose que vous parlez de addEventListener
. Lorsque vous supprimez les éléments DOM, certains navigateurs génèrent ces événements sans les supprimer. C'est pourquoi jQuery fait plusieurs choses lors de la suppression d'un élément:
removeEventListener
. Cela signifie qu'il conserve un tableau avec les écouteurs d'événements ajoutés à cet élément.onclick
, onblur
, etc.) à l'aide de delete
sur l'élément DOM lorsque addEventListener
n'est pas disponible (néanmoins, il possède un tableau dans lequel sont stockés les événements ajoutés).null
pour éviter IE 6/7/8 des fuites de mémoire.