Flex AS3 - 关于变量实例,事件侦听器和垃圾回收

时间:2012-06-26 15:58:15

标签: actionscript-3 flex

问题一:

在以下示例中,我已经向foundMic添加了一个侦听器。我的问题是如果我重新运行foobar.initMic();重新初始化麦克风我最终会在内存中浮动一个死事件监听器,它会被垃圾收集拾取吗?调用.getMicrophone()只是将相同的资源重新连接到foundMic,还是销毁旧的foundMic并在内存中创建一个新的foundMic实例。

如果它与findMic完全相同,那么添加事件监听器将无声地失败并且不会创建第二个监听器。但是如果foundMic成为一个新实例,那么它将创建一个新的监听器。然后回到关于垃圾收集的问题,它是否会被认为是无法清理的?

public class foobar {

    public static var foundMic:Microphone = null;

    public static function initMic():void {
        foundMic = Microphone.getMicrophone();
        foundMic.codec = SoundCodec.SPEEX;
        foundMic.setSilenceLevel(0, 5000);
        foundMic.gain = 50;
        foundMic.setUseEchoSuppression(true);
        foundMic.soundTransform.volume = 1;
        foundMic.addEventListener(StatusEvent.STATUS, onMicStatusEvent);
        return;
     }

    public static function onMicStatusEvent(event:StatusEvent):void {
        if (foundMic && !foundMic.muted) someButton.enabled = true;
        else someButton.enabled = false;
        return;
    }

} // END CLASS

问题二:

基于问题一,如果我在添加侦听器之前添加了一个删除侦听器,那么第一次运行该方法时第二次运行时是否真的删除了侦听器?或者,findMic已经是.getMicrophone()中的一个新实例,因此没有删除任何内容,因为第一个侦听器已经浮动在与之前的foundMic实例关联的内存中?

    public static function initMic():void {
        foundMic = Microphone.getMicrophone();
        .
        .
        .
        foundMic.removeEventListener(StatusEvent.STATUS, onMicStatusEvent);
        foundMic.addEventListener(StatusEvent.STATUS, onMicStatusEvent);
        return;
     }

2 个答案:

答案 0 :(得分:0)

将为findMic分配一个新值,该值是对麦克风的引用 - 不应该进行任何垃圾回收。

垃圾收集器应该启动的情况是这样的:

var someVar:Sprite;
for(var i:int = 0; i < 5; i++)
{
    someVar = new Sprite();
}

在这种情况下,你已经创建了5个新的Sprite对象但最终只有一个分配给someVar变量 - 另外4个应该在某个时候收集垃圾,因为它们没有被任何变量引用。

就问题2而言,第一次调用initMic()时,你所拥有的代码应该会给你一个错误,因为那时还没有onMicStatusEvent监听器。在尝试删除事件侦听器之前,首先测试它是否存在:

if(foundMic.hasEventListener(StatusEvent.STATUS)
{
    foundMic.removeEventListener(StatusEvent.STATUS, onMicStatusEvent);
}
foundMic.addEventListener(StatusEvent.STATUS, onMicStatusEvent);

此代码将始终首先删除事件侦听器(如果存在),然后再添加新的事件侦听器。但是,在这种情况下,我没有看到任何理由,因为addEventListener本身应该可以正常工作 - 多个调用都在同一个对象上,所以无论你调用initMic()多少次,你应该只有一个事件监听器正在运行 - 无需手动删除监听器,然后重新创建。

答案 1 :(得分:0)

以下是事件侦听器发生的情况。 someObject.addEventListener('someEvent', someFunction) someObject someFunctionremoveEventListener的引用。由于范围在ActionScript中的作用方式,该函数可以访问创建它的代码范围内的所有内容。因此,在调用someObject之前,只要FooBar在内存中,函数所在的实例将保留在内存中。

但是,在您的情况下, 没有实例,因为通过使用静态函数,您的侦听器将在您的类{{1}}被首次引用时存在直到你的swf被带出计算机的记忆。

在添加侦听器之前没有删除侦听器的任何净效果,因为它与完全相同的对象传递完全相同的功能,而不是两次调用你的函数。

有关事件监听器如何详细工作的更多信息,请check out this blog post