2011-12-12 8 views
11

¿Esto causaría una pérdida de memoria?¿Este código causaría pérdida de memoria?

var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP 

for (var i=0 ; i< 1000 ; i++) 
{ 
    mc = new MovieClip() ; 
    mc.addEventListener(MouseEvent.CLICK , onClick) ; 
} 

¿Y qué tal esto?

for (var i=0 ; i< 1000 ; i++) 
{ 
    var mc:MovieClip ; //<<<<<<< INSIDE LOOP 
    mc = new MovieClip() ; 
    mc.addEventListener(MouseEvent.CLICK , onClick) ; 
} 

"removeEventListener" no se utiliza en cualquier parte del código anterior, por lo que creo que ambos están causando una pérdida de memoria.

+1

Ninguno está causando una pérdida de memoria en este punto, ya que puede necesitar que se pueda hacer clic en todos los 1000 clips de película.Solo cuando haya terminado con los clips de película y desee eliminarlos de la memoria, entrará en juego el problema del detector de eventos. La respuesta de Ascention es correcta, pero la palabra 'would' es importante. – crooksy88

+0

Todos aquí, soy corregido. Nunca volveré a confiar en la documentación de adobe. Ver mi respuesta actualizada. Mi respuesta actual es incorrecta. –

Respuesta

6

Tus 1000 Movieclips tendrán una referencia a tu función onClick. No de la otra manera. Por lo tanto, si tiene dudas es si sus 1000 Movieclips recibirán GCed: Eventualmente, si no tienen otra referencia.

Por otro lado, la referencia en sus clips de película a su función onClick la mantendrá activa (y el objeto al que podría pertenecer). Si esos MC tienen alguna otra referencia que los mantenga con vida.

El siguiente código:

mc.addEventListener(MouseEvent.CLICK , function(ev:Event):void{ trace("I am only a poor anonymous function"); }, false, 0, true); 

tendrá la función de detector GCed muy pronto, ya que no tiene ninguna referencia fuerte.

establecer useWeakReference a verdadero puede ser bastante relevante si su añadir un eventListener a su etapa

stage.addEventListener(MouseEvent.CLICK, someObjectBelowIntheDisplayList.listenerFunction); 

El código anterior se mantendrá el objeto con la función de detector con vida, incluso si no tiene ninguna otra referencia.

someObjectBelowIntheDisplayList.addEventListener(MouseEvent.CLICK, stage.onClick) 

el código anterior no mantendrá su someObjectBelowIntheDisplayList vivo. Cuenta con una referencia a la etapa, pero la etapa no obtiene una referencia a someObjectBelowIntheDisplayList

Editar: Por favor, intente el siguiente código:

import flash.display.MovieClip; 
import flash.events.Event; 

var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP 

function enterframe(ev:Event):void 
{ 
    for (var i=0 ; i< 1000 ; i++) 
    { 
     mc = new MovieClip() ; 
     mc.onClick = function(ev:Event){}; 
     // Use one of the following lines, comment out the other one 
     //mc.addEventListener(MouseEvent.CLICK , onClick) ; // no memory leak 
     stage.addEventListener(MouseEvent.CLICK, mc.onClick); // memory will rise up and up 
    } 
} 

this.addEventListener(Event.ENTER_FRAME, enterframe); 

function onClick(ev:Event):void 
{ 

} 

Este código es compatible con claridad lo que estoy diciendo: Usando mc .addEventListener va a no para aumentar el consumo de memoria. Permanecerá alrededor de 20MB en mi sistema. Al usar la línea con stage.addEventListener y al usar mc.onClick como función de escucha, el consumo de memoria aumentará en cada fotograma.

+0

El código de prueba que he proporcionado arriba crea constantemente 1000 Movieclips en cada cuadro. Si hubo una pérdida de memoria, el consumo de memoria ** ha ** crecer, ya que no se recogerán todos esos objetos. pero son. Al agregar los Movieclips como oyentes al escenario, hay una pérdida de memoria. La referencia siempre es del despachador al oyente, y no al revés. por lo tanto, si ya no se hace referencia al despachador, se destruirá, independientemente de la cantidad de oyentes que pueda tener. – Malyngo

+0

Eres 100% correcto, señor. Estoy corregido. Actualicé mi respuesta con más información. Parece que Adobe ha agregado nueva información desde la última vez que leí la documentación. También solicité que mi respuesta se marque como incorrecta y se le otorgue el crédito. –

+0

¿Cuál es el punto de agregar el evento ENTER_FRAME? ¿No era suficiente el ciclo? –

6

Actualizado, respuesta correcta

Mi respuesta original estaba mal y sinceramente disculpas. Dejaré intactos todos mis comentarios condescendientes y la información para que la vergüenza siempre me recuerde que nunca confíe en nada que Adobe diga de nuevo. La documentación actual ahora dice:

"Si ya no necesita un detector de eventos, elimínelo llamando a removeEventListener(), o podrían surgir problemas de memoria. Los receptores de eventos no se eliminan automáticamente de la memoria porque el recolector de elementos no utilizados elimina el oyente mientras exista el objeto de envío (a menos que el parámetro useWeakReference esté establecido en verdadero). "

Tenga en cuenta que los detectores de eventos SON el tiempo de recogida de basura hay una referencia débil o no, siempre que el objeto de envío se elimine primero. Entonces, en ambos casos, nunca causarán una pérdida de memoria. Solicito al OP que anule mi respuesta como correcta y le doy a @Malyngo el crédito/respuesta correcta + votos ascendentes.

original (mal) y la respuesta (des) información Sigue

Tanto haría. El enlace de un detector de eventos crea una referencia fuerte al objeto original y, por lo tanto, el recolector de elementos no lo limpiará. Debe eliminar los detectores de eventos explícitamente o especificarlos como referencias débiles, que debería ser uno de los parámetros de addEventListener.

Para las personas que sostienen que los oyentes no se detendrán otros objetos de ser basura recogida

http://gingerbinger.com/2010/07/actionscript-3-0-events-the-myth-of-useweakreference/

Resumen del artículo:

"Imaginemos que nuestro jugador muere, y lo queremos Sin embargo, el oyente del evento crea una referencia desde el escenario hacia el reproductor. El escenario es el objeto de visualización superior y siempre está accesible. Por lo tanto, cuando se ejecuta el proceso de barrido de marca, este detector de eventos permite al recolector de basura hop fr om el escenario de nuestro objeto jugador, incluso si hemos borrado todas las demás referencias y lo eliminamos de la lista de visualización ".

De modo que todavía hay al menos un escenario en el que un detector de eventos solo, fuertemente enlazado, puede evitar la recopilación de un objeto.

solución de mejores prácticas:

1) quitarlo de la lista de visualización.
2) Si es un MovieClip, dile que se detenga().
3) Elimine cualquier detector de eventos que el objeto haya creado.
4) Borre las referencias en los objetos principales al establecerlos como nulos.

actualización de nuevo

una pérdida de memoria no significa necesariamente verá la memoria aplicaciones crecen continuamente. Una pérdida de memoria también puede describir simplemente la memoria que se asigna y persiste durante la vida de la aplicación, cuando debe reciclarse. Algo como este código de prueba no será fácilmente detectable. Pero haz que esto suceda N veces durante un juego de una hora de duración y te garantizo que se mostrará. Tuve la misma situación con un algoritmo de encriptación que escribí una vez. Después de un tiempo, mi aplicación comenzó a moverse a 10 o menos fotogramas por segundo, porque la máquina virtual había consumido una tonelada de memoria que en realidad ya no estaba usando, pero todavía estaba administrándola.

1

Ambos ejemplos son los mismos, ya que actionscript se basa en ecmascript 3 que no tiene ámbito de bloque.

editar: Permítanme ser más específico: no hay alcance de bloque, pero hay alcance de función en ActionScript.

Al igual que con la pérdida de memoria, los objetos permanecerán en la memoria.

+2

"No tiene ámbito de bloque" es falso. Si quiere decir que el alcance no tiene relación con la asignación de memoria y la desasignación, esa es una historia diferente, pero decir simplemente que no hay un alcance de bloque en sí es falso. –

+0

De hecho, diría que es cierto siempre que no cuente una función como un alcance de bloque y la trate como un ámbito propio. (Que de nuevo, técnicamente cierto). – WORMSS

+6

Creo que lo que quiere decir JNissi, es que AS3 usa elevación variable, por lo que declarar una variable dentro o fuera del ciclo tiene el mismo efecto;) – Patrick