2012-06-14 116 views
0
public class MyButton extends Sprite 
{  
    public function MyButton(defaultHandler:Function)  
    {  
     addEventListener(MouseEvent.CLICK, defaultHandler);  
    } 
} 

//主類AS3:會造成內存泄漏嗎?

var myButton:MyButton =new MyButton(someFunction); 
addChild(myButton) 

removeChild(myButton); 
myButton = null; 

IE我從內到我的Button類添加一個匿名鼠標點擊事件處理函數,它在建造時,並沒有明確刪除它時,它從臺上撤下來,並無效。

此對象是否符合垃圾回收器的條件,是否會造成內存泄漏?或者因爲事件監聽器只引用一個本身被刪除的對象,它也會被刪除?

回答

1

Button實例上的事件偵聽器將阻止垃圾收集,除非您專門刪除偵聽器,或者指示偵聽器將成爲弱引用。

addEventListener(MouseEvent.CLICK, defaultHandler, false, 0, true); 

最後一個參數true,傳遞的參數useWeakReference。從docs

將useWeakReference:布爾(默認值= false) - 確定的 參考聽者是否是強還是弱。強引用(默認爲 )會阻止您的偵聽器被垃圾收集。弱 參考沒有。

+0

當設置一個監聽器是軟弱的,去除的責任是轉移到垃圾收集器。你不應該信任GC,因爲它大多是隨機的,所以可能需要一段時間。弱聽者是懶惰的開發人員,他們不負責清理自己的代碼。唯一的例外可能是舞臺上的事件監聽者,但你應該總是自己移除監聽者。 –

+1

同意@MarkKnol,我總是明確地刪除它們。這就是說,這不是OP所要求的。 – sberry

+0

我發現這是一個稍微不同的場景,但有類似的問題: http://stackoverflow.com/questions/8471578/would-this-code-cause-memory-leakage 其中有一個引用: 「事件偵聽器不會自動從內存中移除,因爲只要派發對象存在**,垃圾收集器就不會刪除偵聽器**(除非useWeakReference參數設置爲true)。」 - 所以根據這個,如果監聽器引用的對象不再存在,它不應該**持續存在並且不應該引起泄漏 - 任何人都可以證實這一點嗎? –

1

雖然@ sberry的答案中的點是完全有效的,但仔細看看在這種情況下哪些對象具有相互引用。

如果主類是圍繞用於應用的生命週期,沒有內存泄漏

主要類有它實例化到按鈕類的引用。

Button類具有對來自事件處理函數的主類的引用。

主類將其對該按鈕的引用歸零。

此時,有不再提及按鈕。按鈕可以並將被垃圾收集。

如果主類真的是應用程序的整個生命週期,那就沒有問題了。如果主類消失,但其中一個按鈕對象仍然存在,然後你有內存泄漏(按鈕保持對main的引用,並且main不能被垃圾收集)。

PS:我並不是在反對刪除事件偵聽器時或使用弱引用,我做這兩個做法自己儘可能:)

+0

是的這就是我所說的,如果對象本身不再存在,那麼理論上它的事件聽衆也不應該這樣做。 - 任何人都可以證實這一點? –

+0

[這是一篇來自Adobe的文章](http://www.adobe.com/devnet/flashplayer/articles/garbage_collection.html),它支持我說的話。垃圾收集以兩種方式工作:引用計數(快速),然後「標記和掃描」捕獲具有循環引用的東西(計數永遠不會爲0)。在你的例子中,當你這樣做時,按鈕的引用計數變爲0:'removeChild(myButton); myButton = null;'該按鈕符合垃圾回收的條件,但不能保證什麼時候會發生。 –

+0

只是爲了澄清和回答你的評論中的具體問題:當你在按鈕中使用'addEventListener()'時,該按鈕基本上將該事件映射到一個函數(在這種情況下,在你的主類中定義)。所以,當按鈕變成g/c'd時,這個映射會隨之而來,事件監聽器可以被認爲不再存在。在添加它們時刪除監聽器和/或使用弱引用仍然是一個好習慣:) –