2

我有一个字典,其中保存了movieclips 的数据,如果我停止使用movieclips,我希望数据被垃圾收集。我正在使用弱键参数,它与其他数据完美配合,但是我遇到了问题。

这段代码很好用:

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:我尝试测试 Aaron 所说的话,并想出了一些奇怪的东西......只是迭代字典(不做任何事情)改变了行为:

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

这会保持每帧打印 [object Movieclip],除非我注释掉指示的行,它不会打印任何内容。

4

2 回答 2

1

我相信问题是时间问题之一。我认为当您调用 remove child 时,引用计数直到“框架”的后期才会更新。(我认为这就是正在发生的事情。)

下面的代码说明了为什么我认为这是真的。(我正在使用 flex,但它似乎重现了您的问题。)

下面的代码输出:

[object MovieClip]
here

如果你在 somefoo() 的末尾直接调用 otherfoo,你会得到:

[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>
于 2008-10-17T19:21:32.770 回答
0

在您的示例代码中,您永远不会将电影剪辑添加到字典中,而是将 int 12 添加到字典中?可能是笔误。

If you want the dictionary to have a list of what's currently on the stage, why not have i as a util class instead that listens to Event.ADDED_TO_STAGE and Event.REMOVED_FROM_STAGE and modify the dictionary accordingly? A dictionary doesn't automatically delete references if they get removed from the stage. Also gc in this case has nothing to do with this.

于 2008-10-17T20:10:22.733 回答