大家好,我是奶綠茶
一個好的Flash作品, 除了要有美美的設計與酷炫的動態外
奶小茶我覺的更重要的應該是效能。
我們就以一個EnterFrame事件來說明好了。
在ActionScript2.0時, MovieClip的EnterFrame事件, 當該MovieClip被移除時
其事件也會自動消失。
但在ActionScript3.0, 把該MoviecClip移除, EnterFrame還是會在。
所以當你載入越多的swf檔時, 沒有把前一個swf事件都移除的話, 效能就會越來越差。
那要如何移除事件呢?
通常在移除可視物件時, 就要把所有的事件都取消掉, 這樣才不會一直佔住記憶體。
可視物件有個Event.REMOVE_FROM_STAGE可以加以利用
當物件被從stage移除時, 會廣播該事件。
當偵聽者聽到時, 就把所有有註冊的事件通通取消掉。
被載入的Loaded.swf
在建構函式時就偵聽Event.ENTER_FRAME事件。
按下按鈕 ,unload該swf, 還是看到面版不斷的輸出文字, 也就表示物件移除
不代表事件移除, 所以我們改寫一下Loaded.swf的程式碼。
補充一下:
在google找了些相關資訊, 發現一種不正規的Hack方法
但真的能將記憶體給釋放:
一個好的Flash作品, 除了要有美美的設計與酷炫的動態外
奶小茶我覺的更重要的應該是效能。
我們就以一個EnterFrame事件來說明好了。
在ActionScript2.0時, MovieClip的EnterFrame事件, 當該MovieClip被移除時
其事件也會自動消失。
但在ActionScript3.0, 把該MoviecClip移除, EnterFrame還是會在。
所以當你載入越多的swf檔時, 沒有把前一個swf事件都移除的話, 效能就會越來越差。
那要如何移除事件呢?
//偵聽 clip.addEventListener(事件類型:String , 偵聽者函式:Function) //取消偵聽 clip.removeEventListener(事件類型:String , 偵聽者函式:Function);那什麼時候要取消偵聽?
通常在移除可視物件時, 就要把所有的事件都取消掉, 這樣才不會一直佔住記憶體。
可視物件有個Event.REMOVE_FROM_STAGE可以加以利用
當物件被從stage移除時, 會廣播該事件。
當偵聽者聽到時, 就把所有有註冊的事件通通取消掉。
被載入的Loaded.swf
在建構函式時就偵聽Event.ENTER_FRAME事件。
package { import flash.display.Sprite; import flash.events.Event; public class Loaded extends Sprite{ public function Loaded() { this.addEventListener(Event.ENTER_FRAME, onEventEnterFrame); } private function onEventEnterFrame(e:Event):void { trace(e); } } }載入的主要SWF
package { import com.bit101.components.PushButton; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.net.URLRequest; [SWF(width = "950", height = "500", frameRate = "41", backgroundColor = "#000000", pageTitle = "milkmidi.com")] public class Main extends Sprite{ private var _ldr:Loader public function Main() { _ldr = new Loader(); _ldr.load(new URLRequest("Loaded.swf")); this.addChild(_ldr); var _btn:PushButton = new PushButton(this, 0, 0, "unload", onClick); } private function onClick(e:MouseEvent):void{ _ldr.unload(); } } }發怖成功後, 可以看到面版不斷的輸出文字,
按下按鈕 ,unload該swf, 還是看到面版不斷的輸出文字, 也就表示物件移除
不代表事件移除, 所以我們改寫一下Loaded.swf的程式碼。
package { import flash.display.Sprite; import flash.events.Event; public class Loaded extends Sprite{ public function Loaded() { this.addEventListener(Event.ADDED_TO_STAGE, onAdd2Stage); //當可視物件被加入至場景後, 會發出的事件。 this.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage); //當可視物件被移除後至場景, 會發出的事件。 } private function onRemovedFromStage(e:Event):void { //物件被移除, 所有有偵聽的事件也要手動取消掉。 this.removeEventListener(Event.ADDED_TO_STAGE, onAdd2Stage); this.removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage); this.removeEventListener(Event.ENTER_FRAME, onEventEnterFrame); } private function onAdd2Stage(e:Event):void { this.addEventListener(Event.ENTER_FRAME, onEventEnterFrame); } private function onEventEnterFrame(e:Event):void { trace(e); } } }這樣當物件被除掉後, 也可以一起把事件都取消掉
補充一下:
在google找了些相關資訊, 發現一種不正規的Hack方法
但真的能將記憶體給釋放:
import flash.net.LocalConnection; import flash.system.System; try{ new LocalConnection().connect("foo"); new LocalConnection().connect("foo"); }catch(error : Error){ } //透過try catch,讓Player的garbage collection強製他回收不用的記憶體 System.gc(); //強制執行記憶體回收程序
留言
弟最近正被這個問題困擾了好久,
看過老師的文章後總算是解決一大半了...
希望明年能順利去上老師的AS3課程 :)
不知道是不是一樣的效果,
as3的回收機制觀念有點不太懂
語法如下:
try{
new LocalConnection().connect("foo");
new LocalConnection().connect("foo");
}catch(error : Error){
}
奶大解個謎吧...我只是照做,根本不知道它幹了什麼事。
發現這樣的做法是一種不正規的Hack方法
但真的能清掉記憶體
試試看再補上一句
try{
new LocalConnection().connect("foo");
new LocalConnection().connect("foo");
}catch(error : Error){
}
System.gc();
這樣能清的更乾淨
在flash10的help找不到他的說明,倒是flex3上的有它的help。
有高手說這在air上比較有用,不是很確定。
自己試用system.gc()....感覺差異沒有很大。
奶老师,这个在flash里没方法用,我google了一下,说只能在Debug的下 用player 9 才可以,给在flash里没方法测试,您是在什么环境下用 System.gc();
的啊?
所以還滿常用到這個方法的
有人貼你的文
只是把我的名字拿掉了
唉