代码之家  ›  专栏  ›  技术社区  ›  Sean

有没有从对象中删除未知事件侦听器的方法?

  •  6
  • Sean  · 技术社区  · 18 年前

    我想要一个可重用的按钮,它可以注册为许多不同的回调之一,由外部源决定。设置新回调时,我要删除旧回调。我也希望能够在任何时候清除外部回调。

    public function registerButtonCallback(function:Function):void
    {
      clearButtonCallback();
    
      button.addEventListener(MouseEvent.CLICK, function, false, 0, true);
    }
    
    public function clearButtonCallback():void
    {
      if (button.hasEventListener(MouseEvent.CLICK) == true)
      {
        // do something to remove that listener
      }
    }
    

    建议?

    8 回复  |  直到 15 年前
        1
  •  8
  •   Simon    18 年前

    <mx:Button click="doCallback()" .../>
    
    public var onClickFunction:Function = null;
    private function doCallback():void
    {
        if (onClickFunction != null)
        {
            onClickFunction(); // optionally you can pass some parameters in here if you match the signature of your callback
        }
    }
    

    包含按钮的控件的使用者将使用适当的函数设置onclick函数。事实上,你可以随心所欲地设置它。

        2
  •  4
  •   Triynko    16 年前

    addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
    dispatchEvent(event:Event):Boolean
    hasEventListener(type:String):Boolean
    removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
    willTrigger(type:String):Boolean 
    

    如您所见,有两种方法可以告诉您某一类型的事件是注册了侦听器,还是其父级之一注册了侦听器,但这些方法实际上都不会返回已注册侦听器的列表。

    现在,请去骚扰Adobe,因为它编写了这样一个无用的API。基本上,它们能让你知道“是否”事件流发生了变化,但是它们不能让你用这些信息做任何事情!

        3
  •  3
  •   geraldalewis    18 年前

    将侦听器存储为道具。添加另一个事件时,请检查侦听器是否存在,如果存在,请调用removeEventListener。

    或者,重写按钮的addEventListener方法。调用addEventListener时,在字典对象中将闭包添加到事件之前将其存储。再次调用addEventListener时,请将其删除:

    
    var listeners:Dictionary = new Dictionary();
    
    

    override public function addEventListener( type : String, listener : Function, useCapture : Boolean = false, priority : int = 0, useWeakReference : Boolean = false) : void {

      if( listeners[ type ] ) {
    
         if( listeners[ type ] [ useCapture ] {
    
            //snip... etc: check for existence of the listener
    
            removeEventListener( type, listeners[ type ] [ useCapture ], useCapture );
    
            listeners[ type ] [ useCapture ] = null;
    
            //clean up: if no listeners of this type exist, remove the dictionary key for the type, etc...
    
         }
    
      }
    
      listeners[ type ] [ useCapture ] = listener;
    
      super.addEventListener( type, listener, useCapture, priority, useWeakReference );
    
    };
    

        4
  •  2
  •   sth    16 年前

    为此,我编写了一个名为EventCurb的子类,请参见 blog

    package
    {
       import flash.events.EventDispatcher;
       import flash.utils.Dictionary;
       /**
        * ...
        * @author Thomas James Thorstensson
        * @version 1.0.1
        */
       public class EventCurb extends EventDispatcher
       {
          private static var instance:EventCurb= new EventCurb();
          private var objDict:Dictionary = new Dictionary(true);
          private var _listener:Function;
          private var objArr:Array;
          private var obj:Object;
    
          public function EventCurb() {
             if( instance ) throw new Error( "Singleton and can only be accessed through Singleton.getInstance()" );
          }
    
          public static function getInstance():EventCurb {
             return instance;
          }
    
          override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
          {
             super.addEventListener(type, listener, useCapture, priority, useWeakReference);
          }
    
          override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
          {
             super.removeEventListener(type, listener, useCapture);
          }
    
          public function addListener(o:EventDispatcher, type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
             // the object as key for an array of its event types
             if (objDict[o] == null)  objArr = objDict[o] = [];
             for (var i:int = 0; i <  objArr.length; i++) {
                if ( objArr[i].type == type)
                trace ("_______object already has this listener not adding!")
                return
             }
             obj = { type:type, listener:listener }
             objArr.push(obj);
             o.addEventListener(type, listener, useCapture, priority, useWeakReference);
          }
    
          public function removeListener(o:EventDispatcher, type:String, listener:Function, useCapture:Boolean = false):void {
             // if the object has listeners (ie exists in dictionary)
             if (objDict[o] as Array !== null) {
                var tmpArr:Array = [];
                tmpArr = objDict[o] as Array;
                for (var i:int = 0; i < tmpArr.length; i++) {
                   if (tmpArr[i].type == type) objArr.splice(i);
                }
    
                o.removeEventListener(type, listener, useCapture);
                if (tmpArr.length == 0) {
                   delete objDict[o]
                }
             }else {
                trace("_______object has no listeners");
             }
          }
    
          /**
           * If object has listeners, returns an Array which can be accessed
           * as array[index].type,array[index].listeners
           * @param   o
           * @return Array
           */
          public function getListeners(o:EventDispatcher):Array{
             if (objDict[o] as Array !== null) {
                var tmpArr:Array = [];
                tmpArr = objDict[o] as Array;
                // forget trying to trace out the function name we use the function literal...
                for (var i:int = 0; i < tmpArr.length; i++) {
                   trace("_______object " + o + " has event types: " + tmpArr[i].type +" with listener: " + tmpArr[i].listener);
                }
                return tmpArr
    
             }else {
                trace("_______object has no listeners");
                return null
             }
    
          }
    
          public function removeAllListeners(o:EventDispatcher, cap:Boolean = false):void {
             if (objDict[o] as Array !== null) {
                var tmpArr:Array = [];
                tmpArr = objDict[o] as Array;
                for (var i:int = 0; i < tmpArr.length; i++) {
                   o.removeEventListener(tmpArr[i].type, tmpArr[i].listener, cap);
                }
                for (var p:int = 0; p < tmpArr.length; p++) {
                   objArr.splice(p);
                }
    
                if (tmpArr.length == 0) {
                   delete objDict[o]
                }
             }else {
                trace("_______object has no listeners");
             }
          }
       }
    }
    
        5
  •  1
  •   Jonathan Dumaine    17 年前

    我喜欢做的事情是使用一个动态全局类,并在内联中添加对侦听器函数的快速引用。这意味着您希望像我一样在addEventListener方法中拥有listener函数。这样,您可以在addEventListener中使用removeEventListener:)

    试试这个:

    package {
    
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.text.TextField;
    
    [SWF(width="750", height="400", backgroundColor="0xcdcdcd")]
    public class TestProject extends Sprite
    {   
        public function TestProject()
        {
            addEventListener(Event.ADDED_TO_STAGE, Global['addStageEvent'] = function():void {
                var i:uint = 0;
                //How about an eventlistener inside an eventListener?
                addEventListener(Event.ENTER_FRAME, Global['someEvent'] = function():void {
                    //Let's make some text fields
                    var t:TextField = new TextField();
                        t.text = String(i);
                        t.x = stage.stageWidth*Math.random();
                        t.y = stage.stageHeight*Math.random();
                    addChild(t);
                    i++;
                    trace(i);
                    //How many text fields to we want?
                    if(i >= 50) {
                        //Time to stop making textFields
                        removeEventListener(Event.ENTER_FRAME, Global['someEvent']);
                        //make sure we don't have any event listeners
                        trace("hasEventListener(Event.ENTER_FRAME) = "+hasEventListener(Event.ENTER_FRAME));    
                    }
                });
    
                //Get rid of the listener
                removeEventListener(Event.ADDED_TO_STAGE, Global['addStageEvent']);
                trace('hasEventListener(Event.ADDED_TO_STAGE) = '+hasEventListener(Event.ADDED_TO_STAGE));
    
            });
        }
    
    }   
    

    动态类全局{}

    秘密是动态类全局。使用它,您可以在运行时动态添加属性。

        8
  •  0
  •   user46028    15 年前
    private function callFunction(function:Function):void
    {
         checkObject();
         obj.addEventListener(MouseEvent.CLICK,function);
    }
    
    private function checkObject():void
    {
        if(obj.hasEventListener(MouseEvent.CLICK))
       {
          //here remove that objects
       }
    }