确保不会多次添加相同的事件侦听器

时间:2015-12-17 19:03:16

标签: actionscript-3

我正在实现单例IEventDispatcher类,但遇到了一个问题,有时我多次向我的实例添加相同的事件监听器函数。我尝试保留eventFunctions的数组,如下所示,不要多次添加事件,但它似乎没有按预期工作。

private var eventFunctions:Array =[];

    public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
    if(dispatcher.hasEventListener(type) && eventFunctions.indexOf(listener) > -1){
        trace("adding event listener that already exists " + type + " with function " + listener);
        return;
    }

    dispatcher.addEventListener(type, listener,  useCapture, priority, useWeakReference);
}

1 个答案:

答案 0 :(得分:1)

首先作为注释,添加一个监听器不会出现多次问题 - 只要对象/调度程序,回调函数和useCapture参数相同,它就不会实际添加另一个监听器。

例如:

bob.addEventListener(MouseEvent.CLICK, clickHandler);
bob.addEventListener(MouseEvent.CLICK, clickHandler, false);

function clickHandler(e:Event):void {  trace("clicky"); };

每次点击只会产生1条痕迹。

现在,如果您将其更改为:

bob.addEventListener(MouseEvent.CLICK, clickHandler, false);
bob.addEventListener(MouseEvent.CLICK, clickHandler, true); //<-- use capture is true on this one

现在每次点击你会得到两条痕迹。

现在,如果除了第一点之外,你仍然需要在单身人士中跟踪所有听众,我建议做这样的事情:

//instead of an array, use a dictionary so you can have weak keys that don't prevent your objects from being garbage collected
private static var listeners:Dictionary = new Dictionary(true);

//you need to pass the dispatcher into the function (missing from your question code)
public function addEventListener(dispatcher:EventDispatcher, type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {

    //check is there a record in the dictionary for this object (array)
    if(listeners[dispatcher]){

        //loop through the array and see if there are any matches
        for(var i:int=0;i<listeners[dispatcher].length;i++){
            if(listeners[dispatcher][i] && listeners[dispatcher][i].listener == listener
                && listeners[dispatcher][i].type == type 
                && listeners[dispatcher][i].useCapture == useCapture
                && listeners[dispatcher][i].useWeakReference == useWeakReference){

                trace("adding event listener that already exists " + type + " with function " + listener);
                return;
            }
        }
    }

    //add the listener to the dispatcher
    dispatcher.addEventListener(type, listener,  useCapture, priority, useWeakReference);

    //if no record exists yet, create the array and associate it with this dispatcher
    if(!listeners[dispatcher]) listeners[dispatcher] = new Array();

    //add the parameters just used to the array.
    listeners[dispatcher].push({listener: listener, useCapture: useCapture, useWeakReference: useWeakReference});
}

//you will need a way to remove the listeners as well
public function removeEventListener(dispatcher:EventDispatcher, type:String, listener:Function, useCapture:Boolean = false):void {
    if(listeners[dispatcher] && listeners[dispatcher].length > 0){

        //loop through the array and see if there any matches
        for(var i:int=0;i<listeners[dispatcher].length;i++){
            if(listeners[dispatcher][i] && listeners[dispatcher][i].listener == listener
                && listeners[dispatcher][i].type == type 
                && listeners[dispatcher][i].useCapture == useCapture){

                //remove the event form the dispatcher
                dispatcher.removeEventListener(type, listener, useCapture);

                //remove the item from the array
                listeners[dispatcher].splice(i,1);

                //if the array is now empty, remove the dictionary item
                if(listeners[dispatcher].length < 1) delete listeners[dispatcher];

                //exit the function now
                return;
            }
        }
    }
}