如何从AS3中的对象自动删除事件侦听器

时间:2012-09-07 20:35:53

标签: actionscript-3 flash events event-handling

我正在开发小型Flash游戏。游戏包含20个级别和主菜单。级别之间的转换是通过删除帧上的每个对象以及所有事件侦听器来实现的。然后代码添加下一级别的对象......

捕获和删除事件侦听器由以下代码完成:

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);
        arrListeners.push({type:type, listener:listener});

    }

    private function clearEvents():void
    {
       for(var i:Number = 1; i<arrListeners.length; i++){
          if(this.hasEventListener(arrListeners[i].type))
        {
             this.removeEventListener(arrListeners[i].type, arrListeners[i].listener);
          }
       }
       arrListeners = []
    }

此代码重写内部addEventListeners,并使每个Listener都添加到数组中。第二个函数检查EventListeners是否仍然存在(不是prevoiusly删除),只是从数组中删除每个Listener。

此代码适用于分配给舞台的EventListener。但是,当EventListener直接分配给Object时,它不会添加到数组中,因此以后不会自动删除它。

我知道当您删除对象时,也会删除分配给它的事件侦听器。但是当我再次添加该对象时,Listeners会运行两次。你可以自由地移动关卡,这样你就可以来回走动。当你回去我收到问题。系统被过度使用并且速度慢,因为正在运行的事件监听器的数量增加了一倍。

那么,您是否可以修改此代码或者给我一个建议如何捕获分配给Object的EventListener并最终删除它们。

代码:

package

{
     Public Class Main extends MovieClip
     {
          Public function Main()
          {
               Intro();
          }
          Private function Intro():void
          {
             //Constructor contains a lot of addChild and a EventListeners. So I will upload what I think i important for this problem.
             Play_btn.addEventListener(MouseEvent.CLICK, clicked);
             function clicked (e:MouseEvent):void
             {
                 clearEvents();
                 clearChild(); // function that removes all children on stage
                 FirstLevel();
              }
           }
           Private function FirstLevel():void
           {
              //Also adding children and EventListeners, that affect the gameplay
              Next_level_btn.addEventListener(MouseEvent.CLICK, clicked1);
              function clicked1 (e:MouseEvent):void
             {
                 clearEvents();
                 clearChild();
                 SecondLevel();
              }
              Main_Menu_btn.addEventListener(MouseEvent.CLICK, clicked1);
              function clicked1 (e:MouseEvent):void
              {
                 clearEvents();
                 clearChild(); 
                 Intro();
               }
            }

等等接下来的20个级别。

感谢您的建议。

2 个答案:

答案 0 :(得分:0)

数组索引从0开始,clearEvents应该是:

 private function clearEvents():void
 {
     for(var i:int= 0; i<arrListeners.length; i++){
        if(this.hasEventListener(arrListeners[i].type))
        {
             this.removeEventListener(arrListeners[i].type, arrListeners[i].listener);
        }
     }
     arrListeners = []
 }

不确定这是否能解决您的问题。如果您在添加新对象时创建了事件侦听器,则应在销毁/删除对象时删除这些侦听器。

答案 1 :(得分:0)

删除对象(removeChild(object)不会自动删除它的事件侦听器。你需要自己做。这样的事情可以奏效:

在类构造函数中:

super.addEventListener(Event.ADDED_TO_STAGE,addedToStage,false,0,true);  //only if you want the listeners added back again the next time this object is added to the stage  eg. addChild(this)
super.addEventListener(Event.REMOVED_FROM_STAGE,removedFromStage,false,0,true);

处理程序:

//this runs whenever the object is added to the display list
//if you don't want the listeners re-added, remove this function.
private function addedToStage(e:Event):void {
    for(var i:int=0; i<arrListeners.length; i++){
        super.addEventListener(arrListeners[i].type, arrListeners[i].listener, arrListeners[i].useCapture, arrListeners[i].priority, arrListeners[i].useWeakReference);
    }
}

//this runs whenever the object is removed from the display list
private function removedFromStage(e:Event):void {
    for(var i:int=0; i<arrListeners.length; i++){
        super.removedEventListener(arrListeners[i].type, arrListeners[i].listener, arrListeners[i].useCapture);
    }

    //OR if you want the listeners gone forever, use your clearEvents() method instead of the for loop above
}

当项目从显示列表中删除时,这将使您的侦听器停止侦听,并在添加时重新添加它们。您必须修改数组以包含其他侦听器信息,如捕获阶段和weakReference。如果您不想再次添加它们,只需在removedFromStage处理程序中调用clearEvents()并完全取出addedToStage侦听器/处理程序。

这假设您发布的代码(以及我的附加内容)是您想要应用的所有对象的基类。