【问题标题】:make sure the same event listener is not added more than once确保不会多次添加相同的事件侦听器
【发布时间】:2016-03-24 09:02:59
【问题描述】:

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

【问题讨论】:

  • 您似乎从未填充数组?除其他事项外。还有比你展示的更多吗?如果你有多个事件回调同一个函数怎么办?这种方法也否定了弱引用的好处。
  • 我建议仅在 useweakreference = false 时跟踪事件/侦听器。这是相当重要的。我个人使用 Object 来跟踪事件类型(因为它们都是字符串),然后在我的 Object 键中存储 Vector. 。当 useweakreference 和 usecapture 为 true 时,我也会绕过系统

标签: actionscript-3


【解决方案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;
            }
        }
    }
}

【讨论】:

  • 这都是我脑子里写的,所以未经测试,可能有错别字。
  • 如果您使用 useweakreference = true 跟踪事件集,您将破坏 useweakreference 系统。最好不要触摸使用 useweakreference = true 设置的事件(意味着根本不跟踪它们)
  • 接受这一点,因为它回答了发布的问题。我不理解我的问题以及我应该理解的问题,它与我发布的内容并不完全相关,但我现在已经解决了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 2020-06-29
  • 1970-01-01
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多