在講listener 和 this關(guān)鍵字之前,我們先來講講一個高級話題:弱引用的使用原則。
新手可以不看,因為暫時用不到。但這個話題很有必要。當設(shè)計大型RIA應(yīng)用程序時,弱引用必須要了解。 弱引用從原則上來講,其引入是為了防止無意識的對象保留(unintentional object retention)引起的內(nèi)存泄漏。 什么是無意識的對象保留?一般情況下,對象的邏輯生命周期和實際生命周期應(yīng)當相同。但是在某些情況下,比如事件偵聽器機制,我們可能會創(chuàng)建一個引用,它在內(nèi)存中生存的時間比我們預(yù)期的要長很多。比如說,下面的例子中,即使刪掉了偵聽器lis,但事件還是能被繼續(xù)捕捉。這是由于并沒有removeEventListenr,那么系統(tǒng)中還會保留著對偵聽器的引用。 如果沒有把addEventListener中對偵聽器的持有改成弱引用,那么這個偵聽器會一直存在、耗掉內(nèi)存不被人發(fā)覺。但如果設(shè)成了弱引用,那么垃圾回收器過段時間后會將偵聽器占用的內(nèi)存回收,此時偵聽器從物理意義上才真正的被銷毀了。 在銷毀之前,這個偵聽器還會繼續(xù)存在,繼續(xù)作用。這就是為什么下例中雖然已經(jīng)把useWeakReference設(shè)為了true,但是還是會有作用。 那么什么時侯垃圾回收器(Garbage Collector)才會來回收呢? 唔,這要看它高興了,快的話10分鐘,慢的話一個月。哈哈,開玩笑,垃圾回收器的工作時間咋一看確實是不可測的,但也有規(guī)律可循。但這個問題探討在本系列教程中顯得過于艱深,黑羽會單獨撰文來說明垃圾回收器的部分工作機制。
那么推論來了,我們憑什么要把useWeakReference設(shè)為false呢?除非我們有意要讓某個偵聽器在失去了其他所有引用的時候還要工作,才有可能這樣做。但誰會有這樣瘋狂的想法呢?道哥還是包世宏? 所以,我建議,大家不妨養(yǎng)成習(xí)慣,把useWeakReference設(shè)為true。 當然最好的做法是始終記得不用偵聽器了,一定要removeEventListener。在這一點上,我們要堅持“始亂終棄”!
//這個是Document Class,建個fla,綁定這個class。忘了,就看我第三篇教程。 package { import flash.display.MovieClip; import flash.events.EventDispatcher; import flash.events.MouseEvent;
public class LearnEvents extends MovieClip { function LearnEvents() { var lis:Function = function () { trace ("聽到了鼠標Click事件!"); } var kingda_s:KingdaSprite = new KingdaSprite(0xFFCC00, "kingdaSquare"); addChild(kingda_s); kingda_s.addEventListener(MouseEvent.CLICK, lis, false, 0, true); //瞧,最后一個參數(shù),已經(jīng)把弱引用設(shè)為true了 lis = null; //這一句,我已經(jīng)從邏輯上刪掉lis了,大家作證啊 trace ("偵聽器還在嗎?:"+ lis); //lis也確實指向null了。但你只要繼續(xù)點擊方塊,你會發(fā)現(xiàn)Click事件仍然被捕捉到。 } } } import flash.display.Sprite; import flash.events.MouseEvent;
//這個類就是畫一個矩形, class KingdaSprite extends Sprite { public var nickname:String; public var ColorNum:uint; //colorNumber就是#ffcc00這種類型的數(shù),在AS3中推薦用新的uint型來標記它 public function KingdaSprite(colorNumber:uint, nameString:String) { ColorNum = colorNumber; nickname = nameString; graphics.beginFill(ColorNum); graphics.drawRect(0,0,100,100); graphics.endFill(); } }
Listener和As2.0有何不同,和this關(guān)鍵字的“改進了的記憶力” DOM Level 3中規(guī)定的是用Object來做listener。該Object有用來處理事件的方法(method)。 AS3雖然是按照DOM Level 3事件機制設(shè)計的,但也不完全聽話,有自己獨立的想法。在AS3中,偵聽器就是函數(shù)。也只能用函數(shù)來偵聽。 其實在ActionScript3中,F(xiàn)unction實質(zhì)也是一種特殊的Object,和AS2.0有相似之處。 見我的文章:ActionScript高級技巧:深入了解Function 因此AS3.0為什么限定用Function,這和它的架構(gòu)有關(guān),不細說了。 但有趣的是,在AS3.0中,對IEventDispatcher的定義中,仍然按照DOM3標準用Object來做Listener。見黑羽上一篇教程和隨后的評論。 那么問題來了,function中this關(guān)鍵字的指向會怎樣? AS2.0開發(fā)者對AS2.0 事件機制中 this關(guān)鍵字的水性楊花應(yīng)該深有認識。如果用function做偵聽器,那么誰發(fā)出事件,this就指向誰。這就等于對象之間亂搞關(guān)系,啊呀呀。所以MM派了一個Delegate代理警察類來管理。唉,糜亂的歲月不堪回首啊。
//ActionScript 2.0例子:拷貝以下代碼到第一幀,拖一個button到舞臺,命名為kingda_btn; function lisFunc() { trace ("親愛的,你會指向誰:"+ this.name); //我們本意應(yīng)當是指向_root; }
kingda_btn.addEventListener("click", lisFunc); //點一下button,看看指向誰。
函數(shù)在哪個對象里(應(yīng)該叫method),那么this就指向誰。不在對象里,那么就指向global。
//http://www.kingda.org package { import flash.display.Sprite; import flash.events.MouseEvent;
public class AddListener extends Sprite { public function AddListener() {
//用package外面定義的類KingdaSprite創(chuàng)建一個實例,由于同文件中,所以不用import啦 var outsideChild:KingdaSprite = new KingdaSprite(0x00FF00, "outside_sprite"); addChild(outsideChild);//沒有了這一句,你啥都看不到。 outsideChild.addEventListener(MouseEvent.CLICK, inclassHandler);//注冊類里面的偵聽器 outsideChild.addEventListener(MouseEvent.CLICK, outsideHandler);//注冊類外面的偵聽器 }
private function inclassHandler(event:MouseEvent):void { trace("類里面的偵聽器偵聽到MouseEvent事件: " + event); trace("this關(guān)鍵字指向:"+this); } } }
function outsideHandler(event:MouseEvent):void { trace("類外面的偵聽器偵聽到MouseEvent事件: " + event); trace("this關(guān)鍵字指向:"+this); }
import flash.display.Sprite; import flash.events.MouseEvent;
//這個類就是畫一個矩形,然后你點擊這個矩形會發(fā)出標準鼠標click的事件 class KingdaSprite extends Sprite { public var nickname:String; public var ColorNum:uint; //colorNumber就是#ffcc00這種類型的數(shù),在AS3中推薦用新的uint型來標記它 public function KingdaSprite(colorNumber:uint, nameString:String) { ColorNum = colorNumber; nickname = nameString; graphics.beginFill(ColorNum); graphics.drawRect(0,0,100,100); graphics.endFill(); } }
出處:藍色理想
責(zé)任編輯:moby
上一頁 強大的事件機制 [3] 下一頁
◎進入論壇Flash專欄版塊參加討論
|