大家好,我是奶綠茶
一個好的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);
}
}
}
載入的主要SWFpackage {
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();
的啊?
所以還滿常用到這個方法的
有人貼你的文
只是把我的名字拿掉了
唉