2010-04-09 7 views
9

Kann jemand ein Beispiel von as3-Code (speziell Ereignis-Listener enthalten), die ein einfaches Beispiel für etwas, das Speicher auslaufen könnte ... Posted könnte man hoffentlich auch eine Lösung für das Problem angezeigt werden?AS3 Memory Leak Beispiel

Die Frage ist: Was ist ein einfaches Beispiel für undichte Speicher in einem AS3 Event Listener und wie können Sie es lösen?

+0

Ist das eine Hausaufgabenfrage oder so? – davr

+1

Nein, aber ich habe es irgendwie wie einen haha ​​gestellt ... Die Idee ist, ein gutes 'Goto'-Beispiel zu haben, wenn man allgemein über Speicherlecks nachdenkt. Ein gutes "Anti-Pattern" sozusagen. – Skawful

Antwort

7
public class MySprite extends Sprite { 

    public function MySprite() { 
     if(stage) { 
      init(); 
     } else { 
      addEventListener(Event.ADDED_TO_STAGE,init); 
     } 
    } 

    private function init(e:Event = null):void { 
     stage.addEventListener(Event.RESIZE,handleStageResize); 
    } 

    private function handleStageResize(e:Event):void { 
     // do some processing here. 
    } 

} 

Irgendwo anders:

var mySprite:MySprite = new MySprite(); 
someHolder.addChild(mySprite); 

Nun, wenn zu einem späteren Zeitpunkt Sie mySprite entfernen, es wird immer noch um im Gedächtnis hängen, weil sie selbst hinzugefügt hat (oder einen Verweis auf sich selbst) zu die Stufe in der Methode init().

In diesem Szenario können Sie den Listener, der der Bühne hinzugefügt wird, wenn mySprite aus der Anzeigeliste entfernt wird, am besten vermeiden.

private function init(e:Event = null):void { 
     addEventListener(Event.REMOVED_FROM_STAGE,cleanUp); 
     stage.addEventListener(Event.RESIZE,handleStageResize); 

    } 

    private function cleanUp(e:Event):void { 
     stage.removeEventListener(Event.RESIZE,handleStageResize); 
    } 

Ich bin sicher, dass andere Menschen Ihnen sagen schwache Verweise zu verwenden, wenn die Zuhörer auf die Bühne hinzufügen, aber Sie sollten auf jeden Fall Ihre Zuhörer entfernen. Wenn Sie dies nicht tun, wenn Sie mySprite aus der Anzeigeliste entfernen und keine weiteren Referenzen darauf haben, wird es für GC infrage kommen und schließlich aus dem Speicher gelöscht werden. Aber bis das passiert, wird der Code in handleStageResize() weiterhin ausgeführt.

+2

+1 - Richtige GC in Flash ist wichtig, und für viele Menschen, die Autodidakt sind, kein offensichtliches Problem. – Bosworth99

0

Ich werde nicht ein Beispiel dafür, aber ich werde es ein wenig erklären. Es gibt 2 Situationen, die Sie hier beschreiben.

  1. Speicherlecks
  2. Prozessor

AS3 Griffe Speicher und Prozessoroperationen anders überläuft.

Speicherlecks treten auf, wenn viele Objekte erstellt und zerstört werden. Die Objekte verlieren Speicher, wenn sie Referenzen haben, und das Objekt wird zerstört, ohne die Referenzen zu zerstören - wodurch ein Speicherblock eines unbenutzten Objekts = Leck bleibt.

Prozessorüberläufe treten auf, wenn Sie viele Methoden verwenden, die sich gegenseitig referenzieren, ohne die Schleife zu schließen.

4

Ich werde nur @ Juan Antwort verfolgen - GC muss von Grund auf als ein kritischer Aspekt des Anwendungsdesigns betrachtet werden. Wenn Sie ein Objekt erstellen, müssen Sie sich über jeden Verweis darauf im Klaren sein und jede Referenz entfernen und annullieren, um sie richtig zu kennzeichnen. Wenn Sie dieses Objekt im Array referenzieren, zählt das, wenn Sie es in einem Listener referenzieren, das zählt, wenn Sie es über eine lokale Variable referenzieren, das zählt auch (obwohl nur während der Lebensdauer der Funktion), wenn es einfach in der Display-Liste, die definitiv zählt, und weiter und weiter.

Ich gehe so weit zu schreiben meine remove Listener-Anweisungen vor dem Hinzufügen von ihnen nur um sicherzustellen,.

Ich werde fast immer eine öffentliche destroy() -Methode für jedes Objekt schreiben, um innere Objekthierarchien zu behandeln (Elternanrufe zerstören auf Kind, die ihrerseits Aufrufe an Kindern usw. zerstören). Das Entfernen/Nullen eines Elternteils, ohne dies für jedes Kind zu tun, ist eine schlechte GC-Verwaltung.

Und wenn Sie tatsächlich Bedenken haben, dass mem Leck aufgetreten ist, verfolgen Sie System.totalmemory nur um sicherzugehen:

var mem:String = Number(System.totalMemory/1024/1024).toFixed(2) + ‘Mb’; 
trace(mem); // eg traces “24.94Mb” 

Meist - nur um es methodisch sein - es ist nicht Raketenwissenschaft, aber man muss vorsichtig sein.

Beifall -

@ und auch wenn Sie das tun, macht Blitz seine eigene Meinung darüber, wann bis zu einen Sweep tatsächlich tun. Das Beste, was wir tun können, ist sicherzustellen, dass ein Objekt richtig markiert ist und Vertrauen, dass es effizient behandelt wird.