如果您刪除對父對象的所有引用,則不需要刪除其子對象或對子對象的偵聽器(假設沒有對子對象的外部引用)。
標記清除垃圾回收器通過遍歷對象圖從最頂層的對象(即舞臺)開始工作。將所有路徑剪除到圖的一部分中,並且整個子圖將有資格收集,而不管子圖之間有任何引用。
首先,讓我們考慮只是一個顯示列表層次結構,而不事件:
var clip:Sprite = new Sprite();
addChild(clip);
var clip2 = new Sprite();
clip.addChild(clip2);
// cleanup
removeChild(clip);
clip = null;
clip2 = null;
內孩子CLIP2會被垃圾收集,即使我們沒有通過clip.removeChild(clip2)
從其父將其刪除。由於我們刪除了所有對父代clip
的引用和明確的clip2
引用,因此無法訪問它,因此它將被垃圾收集。因此,沒有必要removeChild
後代剪輯。只要確保你清除任何外部引用(在這種情況下,clip2
)。
現在讓我們想象一些事件:
var clip:Sprite = new Sprite();
addChild(clip);
clip.addEventListener(MouseEvent.CLICK, someListener);
var clip2:Sprite = new Sprite();
clip.addChild(clip2);
clip2.addEventListener(MouseEvent.CLICK, someOtherListener);
// cleanup -- the same!
removeChild(clip);
clip = null;
clip2 = null;
你可能會認爲你必須刪除事件偵聽器,但它實際上是沒有必要的。 addEventListener創建從調度程序到偵聽器的引用。也就是說,將偵聽器添加到子對象不會阻止其垃圾收集。在這種情況下,addEventListener
將剪輯引用到root,將clip2引用到root。發生垃圾回收時,即使該偵聽器在那裏,標記也不能從根節點跳轉到剪輯。參考是其他方向,從剪輯到根!所以對象仍然會被垃圾收集。因此,在這種情況下,不必刪除監聽器。也就是說,如果你不確定,這並不會傷害你。
的唯一途徑聽衆可以防止垃圾回收是,如果一個孩子夾在聽父剪輯:
// from inside clip
root.addEventListener(MouseEvent.CLICK, someHandler);
此偵聽器創建一個從根參考夾,所以您必須刪除引用或使用弱引用。既然你使用的是弱引用,你也不必擔心。
確實需要跟蹤很多事情,並且很容易犯錯,所以最好是在您完成對話時刪除聽衆。如果你刪除它們,你將永遠安全。這對於Flash爲您調度的奇怪本地事件非常重要,如Event.ENTER_FRAME和KeyboardEvent.KEY_DOWN,但不是因爲垃圾回收問題:即使剪輯沒有引用並且有資格收集,它仍會繼續接收ENTER_FRAME事件,直到垃圾收集器實際運行在未來的某個不確定點。所以你應該總是刪除ENTER_FRAME監聽器。
但是在使用簡單MouseEvent的小對象圖的情況下,即使您不打擾刪除偵聽器,您也可以。他們不會傷害任何東西,當剪輯從顯示列表中刪除時,他們將不再被分派。你可以只用removeChild
父剪輯並完成它。
如果您想查看正在發生的事情,在Flash Builder,FlashDevelop或FDT中使用Profiler工具查看內存使用情況會很有幫助。如果您想測試這些想法,您也可以使用System.gc();
調用來強制GC以調試模式運行。
你必須刪除所有孩子的所有聽衆。即使父級設置爲空,偵聽器仍然存在。 – jpea 2011-03-25 18:07:18