2010-06-14 124 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

相關問題