MovieClip не удаляется из словаря
-
03-07-2019 - |
Вопрос
У меня есть словарь, в котором хранятся данные для видеороликов, и я хочу, чтобы данные собирались мусором, если я перестаю использовать мувиклипы. Я использую параметры слабых ключей, и они отлично работают с другими данными, однако я столкнулся с проблемой. Р>
Этот код прекрасно работает:
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] каждый кадр, если я не закомментирую указанную строку, где он ничего не печатает.
Решение
Я считаю, что проблема заключается в сроках. Я думаю, что когда вы вызываете 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>
Другие советы
В приведенном здесь примере кода вы никогда не добавляете мувиклип в словарь, а вместо этого int 12? Вероятно, опечатка.
Если вы хотите, чтобы в словаре был список того, что в данный момент находится на сцене, почему бы не использовать i в качестве класса util вместо этого, который прослушивает Event.ADDED_TO_STAGE и Event.REMOVED_FROM_STAGE и соответственно изменяет словарь? Словарь не удаляет ссылки автоматически, если они удалены со сцены. Также gc в этом случае не имеет к этому никакого отношения.