2009年1月6日 星期二

在ActionScript based應用程式中管理記憶體

Sam目前的對於Flash應用程式的作法都是"骨肉分離", 也就是畫面與程式徹底分開, 全部的動作均是由程式控制。 當然這麼作必須搭配各種事件的處理, 所以當使用者反覆開啟彈出視窗時, 偵聽事件的新增與移除就變得非常重要(因為關係到記憶體的消耗)。

Essential Actionscript 3.0作者Colin Moock說:

當一個Sprite物件被 removeChild掉了,參照也移除了,裡頭的Listener並不會立刻停止監聽/執行,除非它被GC收走(並無法預期GC何時會來),如果這個Sprite一直都有其他物件或變數參照到,那該Listener永遠不會消失,裡頭的程式也會不斷地執行!! 這是很糟糕的問題,所以他建議對於每個類別,都要記得規劃類似: destroy(); kill(); dispose(); deactivate();等函式:清除物件裡頭的物件資料,以便幫助GC來收取記憶體。

另外如果你想用System.gc();的話, 它是For Flash Player debugger version only. 對於一般的FlashPlayer無效

所以記得每次事件處理程式加上weak reference: addEventListener(eventType, listener, false, 0, true); 也記得要常常對不必要的listener寫: removeEventListener(type, listener);

weak reference Listener Example:

someObj.addEventListener("eventName", myFunct, false, 0, true);
addEventListener("eventName", function(evt) { ...code... }, false, 0, true);

Ticore大哥的blog有介紹錯誤使用weak reference的例子: http://ticore.blogspot.com/2006/12/as3-weakly-referenced-listener.html

基本上如果將weak reference listener的function獨立出來管理的話則在移除該listener時也要一併處理function所在的物件, 設置為null或remove等...。

另外Grant Skinner在他的blog中提到一種強制執行GC的方式:

try {
  new LocalConnection().connect('foo');
  new LocalConnection().connect('foo');
} catch (e:*) {}

這個方式為使用LocalConnection重複連結兩次則絕對會throw Error出來, 而Grabage Collection則會在出錯時強制執行一次, 以清除記憶體中無效的變數與物件來減少資源耗用

不過他也有說明:

“Again, this should only be used as a development aid. It should never be used in production code!”
意思是這種投機的方法只能用在develope階段, 絕對不要用在產品上。因為try catch耗用的效能實在很可怕

沒有留言:

張貼留言