我正在实现单例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);
}
答案 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;
}
}
}
}