1

仮定 1.というユーティリティ クラスがありますExperiment。選択したスプライトで EnterFrame イベントをリッスンするのに役立ちます。API は次のようになりますExperiment.listenEnterFrame(mySprite, onEnterFrameHandler);

前提 2.Experiment.listenEnterFrameクラスで匿名ハンドラーの使用を許可したい。また、(メソッドを使用せずにcleanUp()) メモリ リークに強くする必要があります。つまり、mySprite への参照は弱くする必要があります。

コードは次のとおりです。

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.system.System;
import flash.utils.Dictionary;
import flash.utils.setTimeout;

public class Experiment extends Sprite
{
    public function Experiment()
    {
        new MemoryLeakTest();
        new NoMemoryLeakTest();
        setTimeout(System.gc, 100);
    }

    private static var dict:Dictionary = new Dictionary(true);

    private static function listener(event:Event)
    {
        dict[event.currentTarget]();
    };

    public static function listenEnterFrame(dispatcher:Sprite, callback:Function):void
    {
        dict[dispatcher] = callback;
        dispatcher.addEventListener(Event.ENTER_FRAME, listener, false, 0, true);
    }
}
}

import flash.display.Sprite;

internal class MemoryLeakTest extends Sprite
{
    function MemoryLeakTest():void
    {
        Experiment.listenEnterFrame(this, function () {
            trace("Memory leak");
        });
    }
}

internal class NoMemoryLeakTest
{
    function NoMemoryLeakTest():void
    {
        Experiment.listenEnterFrame(new Sprite(), function () {
            trace("No Memory leak");
        });
    }
}

上記の例では、MemoryLeakTest インスタンスが削除されることはありません - 「メモリ リーク」を永遠にトレースします。

それについての私の解釈は、でcallback作成されたクロージャーは、インスタンス自体MemoryLeakTestである外部スコープへの参照を保持するということです。MemoryLeakTestこの参照のため、MemoryLeakTestインスタンスをガベージ コレクションできません。

メモリの解放を心配することなく、ユーティリティ メソッドで匿名コールバックを使用できるようにするための回避策はありますか?

4

1 に答える 1

1

AS3 の辞書には既知のバグがあります。関数/メソッドへの参照を格納する代わりに、クロージャ オブジェクトへの参照が格納されます。

つまり、関数参照をディクショナリにキーとして格納する場合、ディクショナリが弱いキーを使用すると、ディクショナリは関数自体ではなくクロージャー オブジェクトを参照するため、すぐに GC のマークが付けられます。

これは、関数参照をディクショナリにとして格納しようとすると、ディクショナリがクロージャ オブジェクトを保持している限り、クロージャ オブジェクトが参照するインスタンスが GC されないことも意味します。(辞書は値ではなく弱いキーを持っています!) これはまさにここで起こっていることです。

于 2012-08-07T13:49:27.557 に答える