从as3中删除ENTER_FRAME EventListener

时间:2012-03-15 13:02:46

标签: actionscript-3 flash

这是我在主要类中的Flash / AS3中的代码。

addEventListener(Event.ENTER_FRAME,function(e:Event){

        if(findObject == true){
            // I want to remove this ENTER FRAME
        }

});

5 个答案:

答案 0 :(得分:13)

试试这个:

e.currentTarget.removeEventListener(e.type, arguments.callee)

答案 1 :(得分:5)

  1. 您不应该在上面的代码中执行操作。

  2. 如果事件的currentTarget没有removeEventListener()方法(可能,但非常不可能),mgraph的代码很可能无法像宣传的那样工作。从编译器的角度来看,虽然您将尝试动态解决一个易于出错的通用对象上的方法,但应小心处理。这是危险的,因为它表明程序员“不知道”她期望通过假设处理和工作的对象是什么样的。假设对于找到解决方案很有帮助,但对于实现解决方案同样不好。

  3. 如果您想要以您的方式优化某些内容,那么,仅仅是FYI这实际上会在符号表(在已编译的SWF文件中)中创建一个唯一的(冗余)名称,这会导致SWF的压缩程度更低。

    如果您在实验中这样做,这很好,但您应该避免在现实生活中的代码。

    还有一件事需要注意:与true常数的比较是100%无用的。如果这样的比较完全有意义(即findObject可能随时评估为false),那么if (findObject) { ... }等同于您的代码的更短版本。 最后,希望匿名函数缺少返回类型声明。除了您将收到编译器警告之外,它在您的示例中不会发生太大变化。一般来说,省略类型声明是一种不好的风格。

    修改

    public function addEventListener(type:String, listener:Function ...):void
    {
        this._listeners[type].push(listener);
    }
    
    public function dispatchEvent(event:Event):void
    {
        for each (var listener:Function in this._listeners[event.type])
            listener(event);
    }
    
    public function removeEventListener(type:String, listener:Function, ...):void
    {
        delete this._listeners[type][listener];
    }
    

    假设您实际上想要实现IEventDispatcher(而不是使用另一个EventDispatcher - 您可能有理由这样做,原因之一是本机EventDispatcher生成大量短期对象 - 事件,您可能希望减少那个。)但是你无法在你的代码中复制event.target或event.currentTurget,因为你无法访问拥有该方法的对象,所以,你可以把它留下来。

    另一个例子:

    public class SomeEvent extends Event
    {
    
        private var _target:NotEventDispatcher;
    
        public function SomeEvent(type:String, someTarget:NotEventDispatcher)
        {
            super(type);
            this._target = someTarget;
        }
    
        public override function get target():Object
        {
            return this._target;
        }
    }
    

    这是我在现实世界中实际看到的东西,这在Mate或类似框架中用于“匿名”将所有事件调度程序连接到某个“母舰事件调度程序”的单个静态实例。

    我不一定能证明这种做法,但从技术上讲,没有什么可以阻止你做其中任何一种。我在上面的帖子中所说的是,在某些情况下,语言会向你承诺,例如,如果你这样做:

    var dispatcher:IEventDispatcher;
    try
    {
        dispatcher = IEventDispatcher(event.currentTarget);
        // now you can be sure this object has removeEventListener
        dispatcher.removeEventListener(event.type, arguments.callee);
    }
    catch (error:Error)
    {
        // but what are you going to do here?
    }
    

    但最常见的情况是你订阅冒泡事件,在这种情况下,你不知道你是否要取消订阅event.target或event.currentTtarget - 因为你不知道哪一个是那个你在听。

答案 2 :(得分:1)

我同意wvxvw。

解决问题的另一种方法是使用变量来控制"状态"您的ENTER_FRAME事件:

private var _state:String;

private function init(e:Event):void {
    addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}

private function loop(e:Event):void {
    switch(_state) {
        case "play":
            // do play stuff
            // when you want to pause
            // goToPause();
        break;
    }
}

// you can call the method below from a button or whatever you want
private function goToPause():void {
    _state = "pause";
    // do some stuff here
    // when you are done, switch "_state" back to "play"
}

在这个例子中,你一直在监听ENTER_FRAME,但它只在_state变量设置为" play"时才会执行操作。您还可以在goToPause方法中删除事件侦听器:

private function goToPause():void {
    _state = "pause";
    removeEventListener(Event.ENTER_FRAME, loop);
}

然而,使用" _state"的好处是切换的事情是,你不必最终得到一堆addEventListeners和removeEventListeners(这可能会发生,这取决于你的循环得到的复杂程度),你必须跟踪。

答案 3 :(得分:0)

如果您希望稍后删除侦听器,则不应使用匿名函数调用。

public function main():void
{
    //...
    //some method, where you add event listener
    //...

    //adding enterFrame event listener
    this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);

    //...

}

private function enterFrameHandler(e:Event)
{

    if(findObject)  // " == true" is not really necessary here.
    {
        // removing enterFrame listener:
        this.removeEventlistener(Event.ENTER_FRAME,enterFrameHandler);
    }
}

答案 4 :(得分:0)

为了完整性与这里提到的其他技术,你正在创建的功能是一个未绑定的闭包,所以你也可以利用这个概念来引用你的函数和调度程序。

var callback:Function;
var dispacher:IEventDispatcher = this;
addEventListener(Event.ENTER_FRAME, callback = function(e:Event){

        if(findObject == true){
            dispacher.removeEventListener(Event.ENTER_FRAME, callback);
        }

});

适用正常的已结算变量规则。