2

ムービークリップのデータを保持するディクショナリがあり、ムービークリップの使用をやめた場合にデータをガベージ コレクションしたいと考えています。弱いキー パラメータを使用しています。他のデータとは完全に連携しますが、問題が発生しました。

このコードはうまく機能します:

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

これは、何も印刷されない指定された行をコメントアウトしない限り、[object Movieclip] をすべてのフレームで印刷し続けます。

4

2 に答える 2

1

問題はタイミングの問題だと思います。remove childを呼び出すと、参照カウントは「フレーム」の後半まで更新されないと思います。(とにかくこれが起こっていると思います。)

以下のコードは、これが正しいと思う理由を示しています。(私はフレックスを使用していますが、問題を再現しているようです。)

以下のコードは次のように出力します。

[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 を追加しますか? おそらくタイプミスです。

ディクショナリに現在ステージ上にあるもののリストが必要な場合は、代わりに i を util クラスとして使用して Event.ADDED_TO_STAGE と Event.REMOVED_FROM_STAGE をリッスンし、それに応じてディクショナリを変更してみませんか? 参照がステージから削除された場合、ディクショナリは参照を自動的に削除しません。また、この場合の gc はこれとは何の関係もありません。

于 2008-10-17T20:10:22.733 に答える