为什么我的事件监听器不止一次触发?

时间:2010-06-14 02:52:01

标签: flash actionscript-3 events

在我的Flash项目中,我有一个有2个关键帧的movieclip。两个帧每个都包含1个动画片段。

第1帧 - Landing
第2帧 - Game

应用程序的流程很简单:

  1. 用户到达着陆页(第1帧)
  2. 用户点击“开始游戏”按钮
  3. 用户被带到游戏页面(第2帧)
  4. 当游戏结束时,用户可以按“再次播放”按钮,将其带回第1步
  5. LandingGame动画片段都链接到定义事件侦听器的单独类。问题是,当我在玩游戏后在第1步结束时,Game事件监听器会针对各自的事件触发两次。如果我第三次完成这个过程,事件监听器会为每个事件触发三次。这种情况一直在发生,所以如果我循环应用程序流7次,事件监听器会触发七次。我不明白为什么会发生这种情况,因为在第1帧,Game movieclip(我认为它的相关类实例)不存在 - 但我在这里显然遗漏了一些东西。

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

    我需要确保事件侦听器只触发一次。任何建议&我将非常感谢您的见解,谢谢!

2 个答案:

答案 0 :(得分:2)

如果同一图层上有两个具有不同剪辑的帧,则每次该帧“进入”时,都会创建该剪辑。当它“离开”时,剪辑被移除,但它仍然会被保留,不会被垃圾收集。因此,下一次帧进入另一个剪辑时,“创建”并获得自己的监听器。最好的办法是在更改帧时删除侦听器。我通常在每个班级都有Event.REMOVED_FROM_STAGE的听众来解决这类问题。如果它被删除,那么你清理剩余的监听器。

您可能还想尝试“弱听众”:

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

“true”使链接“弱”,因此如果删除了一个对象,垃圾收集器就可以将其拾取。我不会完全依赖这个。最好手动删除引用,以便您确定。

这个答案假设很多。如果你发布代码/截图/闪光灯以便更好地诊断它会很有用。

答案 1 :(得分:2)

如果没有看到代码或知道您正在侦听哪些事件以及是谁/什么激发了它们,那么肯定很难知道。

但是,我的猜测是没有收集动画片段(这不一定是内存泄漏!)所以,它们仍然活着并且踢。您可能应该有一个方法将它们设置为“空闲”状态,可以这么说。意思是,你删除了监听器,停止计时器等。这个想法是让你的对象处于不运行任何代码的状态。

动画片段和其他显示对象的简单方法(通常足够好)是侦听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查看活动实例的数量是否下降;如果没有,则很可能是你有泄漏。

相关问题