AS3.0 一些有关内存泄露的问题

AS3.0中对侦听器的改进远远不止以上这些,看一看addEventListener的实现接口:
function addEventListener(eventName:String, 
                          listener:Object,
                          useCapture:Boolean=false,
                          priority:Integer=0,
                          useWeakReference:Boolean=false):Boolean;
哇塞,有三个莫名奇妙的参数。可是当你知道这三个参数背后隐藏的巨大改进之后,相信你要大叫三个哇塞。

第一个神秘参数,目前暂不解释,埋个伏笔,留到EventDispatcher那一节,讲ActionScript3崭新的Event Flow事件流机制.

第二个参数:优先级。

有趣吧,在ActionScript3.0中我们可以控制事件的优先级,从而达到控制function侦听器的执行顺序。如果你不填这个参数,那么事件默认为同一个级别0,事件的执行按先来后到的天经地义的顺序。 

如果设为1,那么事件级别降一个档次,稍后执行。数字越高优先级越高。级别可以为负数。
(注意: Flex Builder 2 Beta3中事件级别是越低越高)

第三个参数,讲的是是否设为弱引用。
兄弟们初学As2.0时一定经常忘了在删除Listener对象时,却忘了removeEventListener吧。这会导致很多莫名奇妙的情况发生。也是最常见的诡异bug种类之一。即使老鸟偶尔也会被阴一把。
最郁闷的是这种情况往往不被发现,在后台默默的消耗大量资源。
现在可以用弱引用可以在某种程度上解决这种bug。
设为true,就是告诉垃圾回收器,这个侦听器function的引用是弱引用。一旦这个侦听器在运行时只剩下了这一个弱引用,那么垃圾回收器可以不理它,直接把它回收咯屁了,节省资源。
从AS3.0引入这个弱引用这个概念就可以看出,AS3.0是如何的重视资源管理和有效率的运用。一个标准的重量级的程序语言必须具有这样的特征。


=================


弱引用的使用原则


弱引用从原则上来讲,其引入是为了防止无意识的对象保留(unintentional object retention)引起的内存泄漏。
什么是无意识的对象保留?一般情况下,对象的逻辑生命周期和实际生命周期应当相同。但是在某些情况下,比如事件侦听器机制,我们可能会创建一个引用,它在内存中生存的时间比我们预期的要长很多。比如说,下面的例子中,即使删掉了侦听器lis,但事件还是能被继续捕捉。这是由于并没有removeEventListenr,那么系统中还会保留着对侦听器的引用。
如果没有把addEventListener中对侦听器的持有改成弱引用,那么这个侦听器会一直存在、耗掉内存不被人发觉。但如果设成了弱引用,那么垃圾回收器过段时间后会将侦听器占用的内存回收,此时侦听器从物理意义上才真正的被销毁了。
在销毁之前,这个侦听器还会继续存在,继续作用。这就是为什么下例中虽然已经把useWeakReference设为了true,但是还是会有作用。
那么什么时侯垃圾回收器(Garbage Collector)才会来回收呢?
唔,这要看它高兴了,快的话10分钟,慢的话一个月。哈哈,开玩笑,垃圾回收器的工作时间咋一看确实是不可测的,但也有规律可循。


那么推论来了,我们凭什么要把useWeakReference设为false呢?除非我们有意要让某个侦听器在失去了其他所有引用的时候还要工作,才有可能这样做。但谁会有这样疯狂的想法呢?道哥还是包世宏?
所以,我建议,大家不妨养成习惯,把useWeakReference设为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); //瞧,最后一个参数,已经把弱引用设为true了
   lis = null;  //这一句,我已经从逻辑上删掉lis了,大家作证啊
   trace ("侦听器还在吗?:"+ lis);  //lis也确实指向null了。但你只要继续点击方块,你会发现Click事件仍然被捕捉到。
  
  }  
 }
}
import flash.display.Sprite;
import flash.events.MouseEvent;


//这个类就是画一个矩形,
class KingdaSprite extends Sprite {
 public var nickname:String;
 public var ColorNum:uint;
 
 //colorNumber就是#ffcc00这种类型的数,在AS3中推荐用新的uint型来标记它
 public function KingdaSprite(colorNumber:uint, nameString:String) {
  ColorNum = colorNumber;
  nickname = nameString;
  graphics.beginFill(ColorNum);
  graphics.drawRect(0,0,100,100);
  graphics.endFill();  
 }
 
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章