匿名函数作为Action Script中的事件处理程序 - 好还是坏?

jay*_*rjo 6 anonymous-function event-handling actionscript-3

我从JS世界来到AS3,我应该承认匿名函数是我的弱点.我倾向于到处使用它们.现在,来到AS3我已经听过很多地方的内容,AS和Flash在处理垃圾收集时非常糟糕,应该清空,处理和删除所有事件处理程序和对象,以避免奇怪和无法解释的内存泄漏崩溃.不确定这部分是什么,但我想从一开始就遵循最佳实践.

所以我的问题是 - 使用匿名函数作为事件处理程序的想法有多糟糕?考虑一下这样的代码:

addEventListener(Event.ENTER_FRAME, function() : void {
    controls.elapsed = stream.time;
});
Run Code Online (Sandbox Code Playgroud)

contorls.elapsed是setter,除了设置视频播放器的当前播放时间外,还更新整个UI,streamNetStream对象,它传输实际视频.

还有很多其他地方匿名功能可以使代码更清晰,更直观.检查以下代码以获得控制栏的简单淡入效果:

public function showControls() : void
    {
        var self:Controls = this;

        if (!visible) {
            visible = true;
            fadeTimer = new Timer(30, 10);
            fadeTimer.addEventListener(TimerEvent.TIMER, function() : void {
                self.alpha += 0.1;
            });
            fadeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, function() : void {
                self.alpha = 1;
            });
            fadeTimer.start();
        }
    }
Run Code Online (Sandbox Code Playgroud)

我完全喜欢它的外观和适合代码,但我担心泄漏.虽然Event.ENTER_FRAME处理程序可能永远不会在这种形式中变得有害,但计时器监听器呢.我应该手动删除这些侦听器,还是一旦我设置fadeTimer = null就会自动删除它们?是否可以正确删除具有匿名功能的侦听器?

ans*_*art 7

刚刚注意到这篇文章 - 有几件事可能对你有用.一个是arguments.callee(它是对你当前函数的引用).这对于删除匿名函数中的引用很有用.此外,可以注意到您可以在addEventListener代码中使用弱引用 - 但是,这对于匿名变量不起作用,因为它们几乎立即得到GC.为简单起见,我重写了这样的代码:(应该工作 - 没有测试过)

private function showControls() : void {

    if (visible) {
        return;
    }

    var self:DisplayObject = this;

    var fadeTimer= new Timer(30,10);
    var handler = function(e:Event) {

        switch (e.type) {

            // timer complete
            case TimerEvent.TIMER_COMPLETE:

                // remove references to this anonymous function -- for garbage collection
                fadeTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, arguments.callee);
                fadeTimer.removeEventListener(TimerEvent.TIMER, arguments.callee);

                // break out
                return self.alpha = 1;

            // timer
            case TimerEvent.TIMER:
                return self.alpha += 0.1;

        }
    }

    fadeTimer.addEventListener(TimerEvent.TIMER, handler);
    fadeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, handler);
    fadeTimer.start();

}
Run Code Online (Sandbox Code Playgroud)


Ric*_*lay 2

在函数方法有效的地方使用函数方法并没有什么问题。就内存泄漏而言,您需要跟踪该对象到舞台上,看看是否可以将其删除。

ENTER_FRAME向控件添加事件处理程序可确保控件具有对匿名函数的引用。由于代码是控件的一部分(或者看起来如此),这很好,因为当控件是时,匿名函数将被删除。

向计时器添加事件处理程序可确保计时器具有对匿名函数的引用。如果计时器正在运行,它将使匿名函数引用保持活动状态,并通过关联保持整个控制。然而,一旦计时器停止,它和函数都应该被收集。

如果一切都失败了,请使用探查器看看!;)