Pregunta

Tengo un Diccionario donde tengo datos para los clips de video, y quiero que los datos se recolecten como basura si dejo de usarlos. Estoy usando los parámetros de las teclas débiles, y funciona perfectamente con otros datos, sin embargo, me he encontrado con un problema.

Este código funciona muy bien:

var mc = new MovieClip();
var dic = new Dictionary(true);
dic[mc] = 12;
mc = null;
System.gc();
System.gc();
for (var obj in dic)
   trace(obj);    //this doesn't execute

Pero cuando realmente uso el movieclip, deja de funcionar:

var mc = new MovieClip();
var dic = new Dictionary(true);
dic[mc] = 12;
addChild(mc);
removeChild(mc);
mc = null;
System.gc();
System.gc();
for (var obj in dic)
   trace(obj);    //this prints [object Movieclip]

¿Por qué sucede esto? ¿Es algo que estoy haciendo mal? ¿Hay alguna solución?

Editar: Sé que para este ejemplo específico puedo usar delete dic [mc] , pero, por supuesto, este es un caso simplificado. En general, no quiero tener que eliminar manualmente el clip de película del diccionario, pero debería ser automático cuando ya no haga referencia a él en el resto de la aplicación.

Edit2: probé lo que Aaron dijo y se me ocurrió algo extraño ... solo iterar el diccionario (sin hacer nada) cambia el comportamiento:

var mc = new MovieClip();
var dic = new Dictionary(true);
dic[mc] = 12;
addChild(mc);
removeChild(mc);
mc = null;

for (var objeto in dic) {}    // <-- try commenting out this line

addEventListener('enterFrame', f);  // I print the contents every frame, to see if
                                    // it gets removed after awhile

function f(evento)
{
    System.gc();
    System.gc();

    for (var objeto in dic)
        trace(objeto);
}

Esto sigue imprimiendo [objeto Movieclip] cada fotograma, a menos que comente la línea indicada, donde no se imprime nada.

¿Fue útil?

Solución

Creo que el problema es uno de los tiempos. Creo que cuando llama a remove child, el recuento de referencias no se actualiza hasta más adelante en el " marco " ;. (Creo que esto es lo que está sucediendo de todos modos).

El siguiente código demuestra por qué creo que esto es cierto. (Estoy usando flex, pero parece que reproduce tu problema).

El código de abajo produce:

[object MovieClip]
here

Si llama a otherfoo directamente al final de somefoo (), obtiene:

[object MovieClip]
here
[object MovieClip]

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" mouseDown="somefoo()">
<mx:Script>
    <![CDATA[
        import mx.core.UIComponent;
        private var dic:Dictionary = new Dictionary(true);
        private var ui:UIComponent = new UIComponent();
        private var mc:MovieClip = new MovieClip();

        private function somefoo():void {
            this.addChild(ui);

            dic[mc] = 12;
            ui.addChild(mc);
            ui.removeChild(mc);
            for (var obj:Object in dic)
               trace(obj);    //this prints [MovieClip]

            this.removeChild(ui);

                            // callLater causes the function to be called in the _next_ frame.
            callLater(otherfoo);
        }

        private function otherfoo():void
        {
            trace("here");
            mc = null;
            System.gc();
            System.gc();

            for (var obj:Object in dic)
               trace(obj);    //this prints [MovieClip]

        }
    ]]>
</mx:Script>
</mx:Application>

Otros consejos

En el código de ejemplo aquí, nunca se agrega el clip de vídeo al diccionario, sino el int 12 en su lugar. Probablemente un error tipográfico.

Si desea que el diccionario tenga una lista de lo que hay actualmente en el escenario, ¿por qué no tengo i como una clase util que escucha a Event.ADDED_TO_STAGE y Event.REMOVED_FROM_STAGE y modifica el diccionario en consecuencia? Un diccionario no elimina automáticamente las referencias si se eliminan del escenario. Además, gc en este caso no tiene nada que ver con esto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top