Flash 为什么我的事件侦听器会多次触发?
在我的Flash项目中,我有一个有两个关键帧的movieclip。两个帧各包含一个电影剪辑 第1帧-Flash 为什么我的事件侦听器会多次触发?,flash,actionscript-3,events,Flash,Actionscript 3,Events,在我的Flash项目中,我有一个有两个关键帧的movieclip。两个帧各包含一个电影剪辑 第1帧-着陆 第2帧-游戏 应用程序的流程很简单: 用户到达登录页(第1帧) 用户点击“开始游戏”按钮 用户被带到游戏页面(第2帧) 游戏结束后,用户可以按“再次播放”按钮,返回到步骤1 Landing和Gamemovieclips都链接到定义事件侦听器的单独类。问题是,当我在玩游戏后返回步骤1时,游戏事件侦听器会为各自的事件触发两次。如果我第三次执行这个过程,事件侦听器会为每个事件触发三次。这一直在发生
着陆
第2帧-
游戏
应用程序的流程很简单:
Landing
和Game
movieclips都链接到定义事件侦听器的单独类。问题是,当我在玩游戏后返回步骤1时,游戏
事件侦听器会为各自的事件触发两次。如果我第三次执行这个过程,事件侦听器会为每个事件触发三次。这一直在发生,因此如果我循环应用程序流7次,事件侦听器将触发7次。我不明白为什么会发生这种情况,因为在第1帧上,Game
movieclip(我假设它的相关类实例)不存在——但我显然遗漏了一些东西
我在其他项目中也遇到过这个问题,并尝试通过首先检查事件侦听器是否存在并仅定义它们(如果不存在)来解决它,但我最终得到了意想不到的结果,并没有真正解决问题
我需要确保事件侦听器只触发一次。如有任何建议和见解,将不胜感激,谢谢 如果在同一层上有两个具有不同剪辑的帧,则每次该帧“进入”时,都会创建该剪辑。当它“离开”时,夹子被移除,但它仍然会被保留在周围,不会被垃圾收集。因此,下一次帧进入不同的剪辑时,它将“创建”并获得自己的侦听器。最好的办法是在更改帧时删除侦听器。我通常通过在每堂课中为
事件设置一个监听器来解决这类问题。如果它被删除,那么您将清理剩余的侦听器
您可能还想尝试“弱侦听器”:
“true”使链接“弱”,因此,如果删除了对象,垃圾收集器可以将其拾取。不过,我不会完全依赖这个。最好手动删除引用,以便您可以确定
这个答案当然假设了很多。如果您发布代码/屏幕截图/FLA以更好地进行诊断,这将很有帮助。如果您在同一层上有两个具有不同剪辑的帧,则每次该帧“进入”时,都会创建该剪辑。当它“离开”时,夹子被移除,但它仍然会被保留在周围,不会被垃圾收集。因此,下一次帧进入不同的剪辑时,它将“创建”并获得自己的侦听器。最好的办法是在更改帧时删除侦听器。我通常通过在每堂课中为事件设置一个监听器来解决这类问题。如果它被删除,那么您将清理剩余的侦听器
您可能还想尝试“弱侦听器”:
“true”使链接“弱”,因此,如果删除了对象,垃圾收集器可以将其拾取。不过,我不会完全依赖这个。最好手动删除引用,以便您可以确定
这个答案当然假设了很多。如果你发布代码/屏幕截图/flas以更好地诊断,这会很有帮助。如果你没有看到代码,也不知道你在听什么事件以及是谁/什么触发了这些事件,就很难确定
但是,我的猜测是,电影嘴唇没有被收集(这不一定是内存泄漏!),因此,它们仍然活着。可以说,您应该有一个方法将它们设置为“空闲”状态。也就是说,删除侦听器、停止计时器等。这样做的目的是将对象置于不运行任何代码的状态
movieclips和其他显示对象的一种简单方法(通常已经足够好了)是侦听添加到\u阶段和从\u阶段事件中删除的\u。这里的想法是,当你的对象被添加到舞台上时,它会“激活”,在你的情况下,当你到达游戏类的第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帧时是“destroy”。“mainLoop”此时应停止跟踪
除此之外,您可能还需要检查是否存在内存泄漏(事实上,您有7个实例并不一定意味着您有泄漏;但在某些情况下,如果GC运行,至少应该释放其中的一些;如果从未发生过这种情况,这是泄漏的症状;尝试强制GC查看活动实例的数量是否减少;如果没有,则很可能有泄漏).如果看不到代码,也不知道您在监听什么事件以及是谁/什么触发了这些事件,就很难确定
但是,我的猜测是,movieclips没有被收集(这不一定是内存泄漏!),因此,它们仍然处于活动状态。您可能应该有一种方法将它们设置为“空闲”也就是说,删除侦听器、停止计时器等。这样做的目的是将对象置于不运行任何代码的状态
movieclips和其他显示对象的一种简单方法(通常已经足够好了)是监听添加到\u STAGE和从\u STAGE事件中删除的\u。这里的想法是,对象在添加到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”跟踪出来,t