2010-04-09 12 views
9

Qualcuno può pubblicare un esempio di codice as3 (in particolare un listener di eventi incluso) che sarebbe un semplice esempio di qualcosa che potrebbe perdere memoria ... si spera anche di pubblicare una soluzione al problema mostrato?Esempio di perdita di memoria AS3

La domanda è: che cosa è un semplice esempio di perdita di memoria in un listener di eventi AS3 e come è possibile risolverlo?

+0

Questa è una domanda sui compiti o qualcosa del genere? – davr

+1

No, ma l'ho messo come un haha ​​... L'idea è di avere un buon esempio di "goto" quando si pensa alle perdite di memoria in generale. Un buon "anti-modello", per così dire. – Skawful

risposta

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. 
    } 

} 

Da qualche altra parte:

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

Ora, se a un certo punto poi si rimuove mySprite, sarà ancora appendere in giro per la memoria, perché si (o un riferimento a se stesso) ha aggiunto alla lo stage nel metodo init().

In questo scenario, il modo migliore per evitare ciò potrebbe essere la rimozione dell'ascoltatore aggiunto allo stage quando mySprite viene rimosso dall'elenco di visualizzazione.

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); 
    } 

sono sicuro che altre persone vi dirà di utilizzare riferimenti deboli quando si aggiunge l'ascoltatore allo stadio, ma si dovrebbe rimuovere i vostri ascoltatori in ogni caso. Se non lo fai, quando rimuovi mySprite dall'elenco di visualizzazione e non hai altri riferimenti ad esso, sarà idoneo per GC e alla fine verrà cancellato dalla memoria. Ma finché ciò non accade, il codice in handleStageResize() continuerà ad essere eseguito.

+2

+1 - Il corretto GC in flash è importante e per molte persone autodidatte non è un problema ovvio. – Bosworth99

0

Non ho intenzione di postare un esempio di questo, ma lo spiegherò un po '. Ci sono 2 situazioni che stai descrivendo qui.

  1. perdite di memoria
  2. processore trabocca

AS3 gestisce le operazioni di memoria e processore diverso.

Memoria Le perdite si verificano quando vi sono molti oggetti creati e distrutti. Gli oggetti perdono memoria quando hanno riferimenti e l'oggetto viene distrutto senza distruggere i riferimenti, lasciando quindi un blocco di memoria di un oggetto inutilizzato = perdita.

Processor Gli overflow si verificano quando ci sono molti metodi che si riferiscono l'un l'altro senza chiudere il ciclo.

4

Mi limiterò a seguire @ la risposta di Juan - GC deve essere considerato da zero come un aspetto critico del design dell'applicazione. Se crei un oggetto, devi essere consapevole di ogni riferimento ad esso, e rimuovere ogni riferimento e annullarlo per segnalare correttamente @. Se si fa riferimento a quell'oggetto nell'array, che conta, se lo si fa riferimento in un listener, che conta, se lo si fa riferimento tramite una variabile locale, che conta anche (anche se solo durante la vita della funzione), se è semplicemente nel elenco di visualizzazione, che sicuramente conta, e così via.

Mi spingo così lontano da scrivere le mie istruzioni di ascolto rimuovi prima di aggiungerle allo solo per essere sicuri che.

Scriverò quasi sempre un metodo public destroy() per qualsiasi oggetto per gestire gerarchie di oggetti interni (le parent calls distruggono sul child, che, a sua volta, chiama destroy su qualsiasi figlio ecc. Ecc.). La semplice rimozione/annullamento di un genitore senza farlo a ogni bambino è una cattiva gestione del GC.

E se si ha effettivamente qualche dubbio sul fatto che la perdita di memoria sia iniziata, tracciare Sistema.totalMemory solo per assicurarsi che:

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

Per lo più - tanto per essere metodico su di esso - non è la scienza a razzo, ma bisogna stare attenti.

Cheers -

@ e anche se lo fai, Flash rende una propria idea su quando farlo in realtà uno sweep. Il meglio che possiamo è assicurarsi che un oggetto sia opportunamente contrassegnato e fidati che verrà trattato in modo efficiente.