2010-06-14 88 views
1

在我的Flash项目中,我有一个有2个关键帧的动画片段。两个帧都包含1个动画片段。为什么我的事件侦听器不止一次发射?

框架1 - Landing
框架2 - Game

应用程序的流程简单:

  1. 用户到达着陆页上(框1)
  2. 用户点击 “开始游戏”按钮
  3. 用户被带到游戏页面(第2帧)
  4. 当游戏结束时, SER可以按下“重新播放”按钮,这使他们回到步骤1

两个LandingGame影片剪辑链接到该定义事件监听器单独的类。问题是,当我在玩游戏后最终返回到步骤1时,事件侦听器会为其各自的事件触发两次。如果我第三次经历这个过程,事件听众会为每个事件触发三次。这一直在发生,所以如果我循环遍历应用程序流7次,事件侦听器会激发七次。我不明白为什么会发生这种情况,因为在第1帧上,movieclip(我假设它的相关类实例)不存在 - 但我明显在这里丢失了一些东西。

我也在其他项目中遇到过这个问题,并尝试通过首先检查事件侦听器是否存在以及如果他们没有定义它们来修复它,但是最终我得到了意想不到的结果解决这个问题。

我需要确保事件侦听器只触发一次。任何建议&洞察力将不胜感激,谢谢!

回答

2

如果在同一图层上有两个带有不同剪辑的框架,每次该框架“进入”时,都会创建该剪辑。当它“离开”剪辑被删除,但它仍然会保持在周围,而不是垃圾收集。所以下一次帧进入不同的剪辑是“创建”,它会得到自己的监听器。你最好的选择是在你改变帧的时候去掉听众。我通常通过在每个班级有一位听众Event.REMOVED_FROM_STAGE来解决这类问题。如果它被删除,那么你清理剩下的听众。

你也可以用“弱听众”实验:

addEventListener(GameEvent.GAME_START, gameStartedHandler, false, 0, true); 

的“真”,使得链接“弱”所以,如果一个对象被删除,垃圾收集器可以把它捡起来。尽管如此,我不会完全依赖这一点。更好地手动删除引用,所以你可以肯定。

这个答案假设很多。如果您发布代码/屏幕截图/ flas以更好地诊断,这会很有帮助。

+0

这很有道理。我现在正在阅读关于GC的内容,并且我确保删除事件监听器,现在它似乎工作正常。我喜欢你使用Event.REMOVED_FROM_STAGE的想法。谢谢!! – 2010-06-14 03:37:03

+0

+1。跟我建议的一样,但你打我30秒! – 2010-06-14 03:37:28

+0

嘿嘿,我已经学会在我的思想中途完成时发布我的答案。然后回去完成它。 Sneaaaaky,查理。 – typeoneerror 2010-06-14 03:38:59

2

没有看到代码或知道你正在听什么事件以及谁/什么触发他们,这确实很难知道。但是,我的猜测是,movieclip没有被收集(这不是一个内存泄漏!),所以,他们仍然是敌手和踢。你可能应该有一个方法将它们设置为“空闲”状态,可以这么说。意思是,你删除了听众,停止定时器等。这个想法是把你的对象置于不运行任何代码的状态。

对于动画片段和其他显示对象来说,一个简单的方法就是侦听ADDED_TO_STAGE和REMOVED_FROM_STAGE事件。这里的想法是,当你的对象被添加到舞台上时,你的对象“激活”,在你的情况下,当你到达游戏类的第2帧时,它会被激活;它“停用”时,它的拆除,也就是说,当你回到框架沿着这些线路1.

东西:

public class Game extends MovieClip { 

    private var _timer:Timer; 

    public function Game() { 
     addEventListener(Event.ADDED_TO_STAGE,init); 
     addEventListener(Event.REMOVED_FROM_STAGE,destroy); 
    } 

    private function init():void { 
     // your init code goes here 
     // just an example: 
     _timer = new Timer(33); 
     _timer.addEventListener(TimerEvent.TIMER,mainLoop); 
     _timer.start(); 
     trace("init"); 
    } 

    private function destroy():void { 
     _timer.stop(); 
     _timer.removeEventListener(TimerEvent.TIMER,mainLoop); 
     trace("destroy"); 
    } 

    private function mainLoop(e:TimerEvent):void { 
     // code for main loop here... 
     trace("mainLoop"); 
    } 
} 

检查的痕迹,看看它的正常工作。你应该看到“init”被追踪出来,然后“mainLoop”只要你留在第2帧中,当你回到第1帧时就会“销毁”。“mainLoop”应该停止在这一点上追踪。除此之外,你可能想要检查是否没有内存泄漏(事实上你有7个实例并不意味着你有泄漏;但是在某些时候,如果GC失败了,至少有一些他们应该被释放;如果这从来没有发生,这是一个泄漏的症状;尝试迫使一个GC,看看是否有多少个盟友实例失效;如果没有,很可能是你有泄漏)。

+0

谢谢你的伟大的代码示例! – 2010-06-14 03:39:41