MovieClip не удаляется из словаря - PullRequest
2 голосов
/ 17 октября 2008

У меня есть словарь, в котором хранятся данные для мувиклипов, и я хочу, чтобы данные собирались мусором, если я перестаю использовать мувиклипы. Я использую параметры слабых ключей, и они отлично работают с другими данными, однако я столкнулся с проблемой.

Этот код прекрасно работает:

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

Но когда я на самом деле использую мувиклип, он перестает работать:

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]

Почему это происходит? Я что-то не так делаю? Есть ли обходной путь?

Редактировать: я знаю, что для этого конкретного примера я могу использовать delete dic[mc], но, конечно, это упрощенный случай. В общем, я не хочу вручную удалять мувиклип из словаря, но он должен быть автоматическим, когда я больше не ссылаюсь на него в остальной части приложения.

Edit2: я пытался проверить то, что сказал Аарон, и придумал просто странные вещи ... просто итерация словаря (ничего не делая) меняет поведение:

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

Это продолжает печатать [объект Movieclip] каждый кадр, если я не закомментирую указанную строку, где он ничего не печатает.

Ответы [ 2 ]

1 голос
/ 17 октября 2008

Я считаю, что проблема заключается в синхронизации. Я думаю, что когда вы вызываете remove child, счетчик ссылок не обновляется до тех пор, пока не появится «кадр». (Я думаю, это то, что происходит в любом случае.)

Код ниже демонстрирует, почему я думаю, что это правда. (Я использую flex, но, похоже, он воспроизводит вашу проблему.)

Код ниже выводит:

[object MovieClip]
here

Если вы вызываете otherfoo напрямую в конце somefoo (), вы получите:

[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>
0 голосов
/ 18 октября 2008

В приведенном здесь примере кода вы никогда не добавляете мувиклип в словарь, а вместо 12 int? Вероятно, опечатка.

Если вы хотите, чтобы в словаре был список того, что в данный момент находится на сцене, почему бы не использовать i в качестве класса util вместо этого, который прослушивает Event.ADDED_TO_STAGE и Event.REMOVED_FROM_STAGE и соответственно изменяет словарь? Словарь не удаляет ссылки автоматически, если они удалены со сцены. Также gc в этом случае не имеет к этому никакого отношения.

...