webentwicklung-frage-antwort-db.com.de

Was ist der richtige Weg, um eine Karteninstanz zu zerstören?

Ich habe kürzlich eine mobile Anwendung für HTML5 entwickelt. Die Anwendung war eine einzige Seite, auf der Ereignisse zur Änderung des Navigationshashs das gesamte DOM ersetzten. Ein Abschnitt der Anwendung war Google Map mit API v3. Bevor die Map div aus dem DOM entfernt wird, möchte ich alle Event-Handler/Listener entfernen und so viel Speicher wie möglich freigeben, da der Benutzer möglicherweise nicht mehr zu diesem Abschnitt zurückkehrt.

Was ist der beste Weg, um eine Karteninstanz zu zerstören?

83

Die offizielle Antwort ist das nicht. Karteninstanzen in einer Einzelseitenanwendung sollten wiederverwendet und nicht zerstört und anschließend erneut erstellt werden.

Für einige Einzelseitenanwendungen kann dies bedeuten, dass die Lösung so umgestaltet wird, dass eine einmal erstellte Karte möglicherweise ausgeblendet oder vom DOM getrennt wird, jedoch niemals zerstört oder neu erstellt wird.

25

Ich füge noch eine zweite Antwort zu dieser Frage hinzu, weil ich nicht das Hin und Her entfernen möchte, das wir durch nachfolgende Kommentare zu meiner vorherigen Antwort hatten.

Ich bin jedoch kürzlich auf Informationen gestoßen, die Ihre Frage direkt ansprechen, und deshalb wollte ich weitergeben. Ich weiß nicht, ob Sie sich dessen bewusst sind, aber während des Google Maps API Office-Stunden vom 9. Mai 2012 diskutierten Chris Broadfoot und Luke Mahe von Google diese Frage von stackoverflow. Wenn Sie die Videowiedergabe auf 12:50 Uhr einstellen, wird in diesem Abschnitt Ihre Frage behandelt.

Im Wesentlichen geben sie zu, dass es sich um einen Fehler handelt, fügen jedoch hinzu, dass sie keine Anwendungsfälle unterstützen, bei denen aufeinanderfolgende Karteninstanzen erstellt/zerstört werden. Sie empfehlen dringend, eine einzelne Instanz der Karte zu erstellen und sie in jedem Szenario dieser Art wiederzuverwenden. Sie sprechen auch über das Setzen der Karte auf Null und das explizite Entfernen von Ereignis-Listenern. Sie haben Bedenken hinsichtlich der Ereignis-Listener geäußert. Ich dachte, es würde ausreichen, die Karte auf Null zu setzen, aber es sieht so aus, als wären Ihre Bedenken gültig, weil sie Ereignis-Listener besonders erwähnen. Sie empfahlen auch, das DIV, das die Karte enthält, vollständig zu entfernen.

Jedenfalls wollte ich das nur weitergeben und sicherstellen, dass es in die Stackoverflow-Diskussion einbezogen wird. Ich hoffe, es hilft Ihnen und anderen.

45
Sean Mickey

Da Sie anscheinend Karteninstanzen nicht wirklich zerstören können, können Sie dieses Problem reduzieren, wenn 

  • sie müssen mehrere Karten gleichzeitig auf einer Website anzeigen
  • die Anzahl der Karten kann sich mit der Benutzerinteraktion ändern
  • die Karten müssen zusammen mit anderen Komponenten ausgeblendet und wieder angezeigt werden (dh sie erscheinen nicht an einer festen Position im DOM).

behält einen Pool von Karteninstanzen. Der Pool verfolgt die verwendeten Instanzen und wenn eine neue Instanz angefordert wird, prüft er, ob eine der verfügbaren Karteninstanzen frei ist: Wenn dies der Fall ist, wird ein vorhandener zurückgegeben Wenn dies nicht der Fall ist, wird eine neue Karteninstanz erstellt, zurückgegeben und dem Pool hinzugefügt. Auf diese Weise haben Sie nur eine maximale Anzahl von Instanzen, die der maximalen Anzahl von Karten entspricht, die Sie gleichzeitig auf dem Bildschirm anzeigen .. __ Ich verwende diesen Code (er benötigt 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
    }
 }
}

Sie übergeben die Startkartenoptionen (gemäß dem zweiten Argument des Konstruktors von google.maps.Map) und geben sowohl die Karteninstanz (auf der Sie Funktionen für google.maps.Map aufrufen können) als auch den Container zurück Sie können die Klasse "myDivClassHereForStyling" mit einem Style versehen und an das DOM anhängen . Wenn Sie das System zurücksetzen müssen, können Sie mapInstancesPool.reset () verwenden. Der Zähler wird auf 0 zurückgesetzt, wobei alle vorhandenen Instanzen für die Wiederverwendung im Pool verbleiben .. In meiner Anwendung musste ich alle Maps auf einmal entfernen und einen neuen Satz von Maps erstellen, sodass es keine Funktion gibt, um eine bestimmte Map zu recyceln Beispiel: Ihre Laufleistung kann variieren. Um die Karten vom Bildschirm zu entfernen, verwende ich die Entfernung von jQuery, wodurch der Container der Karte nicht zerstört wird.

Mit diesem System und mit

google.maps.event.clearInstanceListeners(window);
google.maps.event.clearInstanceListeners(document);

und läuft

google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()

(wobei divReference das vom Instanz-Pool zurückgegebene jQuery-Objekt des div ist.) Bei jedem von mir entfernten Div konnte ich die Speicherauslastung von Chrome mehr oder weniger stabil halten, anstatt sie jedes Mal zu erhöhen, wenn ich Karten lösche und neue hinzufügte Einsen.

11
Paolo Mioni

Ich hätte vorgeschlagen, den Inhalt der Map div zu entfernen und delete für die Variable zu verwenden, die den Verweis auf die Map enthält, und wahrscheinlich eventuelle Listener explizit deleteing.

Es gibt jedoch einen bekannten Fehler , und dies funktioniert möglicherweise nicht.

5
Andrew Leach

Da google gunload () für api v3 nicht zur Verfügung stellt, sollten Sie iframe besser in html verwenden und map.html diesem iframe als Quelle zuweisen. nach Gebrauch machen Sie src als null. Dadurch wird auf jeden Fall der von der Karte belegte Speicherplatz freigegeben.

2
kumar

Wenn Sie die Variable div entfernen, wird der Anzeigebereich entfernt, und die Karte wird ausgeblendet. Um die Karteninstanz zu entfernen, stellen Sie sicher, dass der Verweis auf die Karte auf null und alle Verweise auf andere Teile der Karte auf null gesetzt sind. An diesem Punkt kümmert sich die JavaScript-Garbage Collection um die Bereinigung, wie in: beschrieben. Wie funktioniert die Garbage Collection in JavaScript? .

1
Sean Mickey

Ich denke, Sie sprechen von addEventListener. Wenn Sie die DOM-Elemente entfernen, verlieren einige Browser diese Ereignisse und entfernen sie nicht. Aus diesem Grund führt jQuery beim Entfernen eines Elements mehrere Aktionen aus:

  • Es entfernt die Ereignisse, wenn dies mit removeEventListener möglich ist. Das bedeutet, dass ein Array mit den Ereignis-Listenern beibehalten wird, die es zu diesem Element hinzugefügt hat.
  • Es löscht die Attribute für Ereignisse (onclick, onblur usw.) mit delete für das DOM-Element, wenn addEventListener nicht verfügbar ist (es verfügt jedoch über ein Array, in dem die hinzugefügten Ereignisse gespeichert werden).
  • Das Element wird auf null gesetzt, um IE 6/7/8 Speicherverluste zu vermeiden.
  • Dann wird das Element entfernt.
0