AS3:在函数内声明的对象,对象内的侦听器......它们都得到GC吗?

时间:2013-04-22 21:42:55

标签: actionscript-3 object garbage-collection flashdevelop event-listener

晚上y'所有,

我通常没有必要问,因为有太多的信息,但我找不到 - 至少,不是特别。

这里是要点:我在一个函数中声明一个对象,然后在该对象中打一个监听器。问题:一旦函数运行,对象和函数都会被删除吗?出于显而易见的原因,我不想要没有物体悬挂的随机听众。

如果它有帮助,这里是简化的代码:

(随意让它看起来更漂亮,为此道歉)

public function textSfx(chPos:int, otlPos:int):void {

        var sfxTimer:Timer = new Timer (300, 6);


            sfxTimer.addEventListener(TimerEvent.TIMER, textSfxHandler(chPos));


        sfxTimer.start();
    }

    public function textSfxHandler(chPos:int):Function
    {
        return function(evt:TimerEvent):void
        {
            trace("char being affected is: " + chPos);
        }
    }

var sfxTimer:Timer = new Timer (300, 6); sfxTimer.addEventListener(TimerEvent.TIMER, textSfxHandler(chPos)); sfxTimer.start(); } public function textSfxHandler(chPos:int):Function { return function(evt:TimerEvent):void { trace("char being affected is: " + chPos); } }

它的工作非常好,但我担心听众无家可归。当然不是这样,对吧? RIGHT ??

P.S。由于多个元素需要同时定时器,因此在函数内部声明了对象,而这些定时器并不适用于单个外部声明的定时器。

2 个答案:

答案 0 :(得分:0)

Timer对象和anonymus函数将保留在内存中,直到Timer链接到事件侦听器。您的代码不会让GC完成其工作。

添加监听器(第5个参数)时可以使用弱引用参数:

sfxTimer.addEventListener(TimerEvent.TIMER, textSfxHandler(chPos), false,0,true);

但无论如何使用匿名函数是不好的做法

以下代码是否适用于您的情况?请注意,我使用命名侦听器,而不是每次都重新创建它们:

    private var timerPool:Dictionary = new Dictionary();
    public function textSfx(chPos:int, otlPos:int=0):void {
        var sfxTimer:Timer = new Timer (300, 6);
        timerPool[sfxTimer] = chPos;
        sfxTimer.addEventListener(TimerEvent.TIMER, textSfxHandler);
        sfxTimer.addEventListener(TimerEvent.TIMER_COMPLETE, textSfxComplete);
        sfxTimer.start();

    }
    public function textSfxHandler(e:TimerEvent):void
    {
        var sfxTimer:Timer = e.target as Timer;
        trace("char being affected is" + timerPool[sfxTimer]);
    }
    public function textSfxComplete(e:TimerEvent):void {
        var sfxTimer:Timer = e.target as Timer;
        sfxTimer.removeEventListener(TimerEvent.TIMER, textSfxHandler);
        sfxTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, textSfxComplete);
        delete timerPool[sfxTimer];
    }

答案 1 :(得分:0)

在太空中,没有人能听到你尖叫
这就是你在这里所拥有的。你有一个没有人知道的Timer,你有一个只有Timer知道的回调。因此,不是将你的宇航员(计时器)绑在你的宇宙飞船上,而是用你的螺丝刀绑在他身上,而是将它们中的两个系在一起,然后让它们随时离开,垃圾收集器可以随时将它们舀起来,无论计时器是否已经发射,回调是否已经运行。

您需要做的是添加一些类型的引用以保留您的Timer,或者您无法保证它将触发/触发回调。您可能也可以声明一个变量来保存该计时器(请注意,然后您将在创建闭包时传递该变量)。如果您选择使用词典,您希望使用弱键,否则您只是将宇航员拴在一侧的螺丝刀上,另一侧是扳手。

这意味着执行需要使包含计时器的变量为空并停止计时器(因为如果使用匿名函数,则无法删除事件侦听器)创建Timer的实例。

有关这些内容如何运作的更多信息,请查看this blog post