ActionScript3.0的事件体系结构基于两个关键的参与者:侦听器和侦听器所注册的对象。当对一个对象添加了侦听器后,该对象的内部侦听器列表就有了对该侦听器的引用。默认情况下,对一个对象添加了侦听器之后,该对象的内部侦听器列表都保存对该侦听器的引用,直到该侦听器被removeEventListener()方法取消注册,如果没有取消注册,该侦听器会一直被引用。被搁置的侦听器是导致内存浪费的一个重要方面。
下面通过一个实例来说明该问题:假设现在有一个Timer对象和一个篮球(Basketball)实例,Timer对象设定每隔1s让Basketball实例重新计算一下自己在舞台中的位置(为方便起见,让Basketball实例随机在舞台中找一位置)。
Main类
package
{
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Main extends Sprite
{
private var timer : Timer;
private var basketball : Basketball;
public function Main()
{
super();
timer = new Timer(1000, 20);
basketball = new Basketball();
addChild(basketball);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerComplete);
timer.start();
}
private function onTimer(e : TimerEvent) : void {
basketball.calculatePosition();
}
private function timerComplete(e : TimerEvent) : void {
basketball.removeSelf();
basketball = null;
}
}
}
Basketball类
package
{
import flash.display.Sprite;
public class Basketball extends Sprite
{
public function Basketball()
{
super();
this.graphics.beginFill(Math.random() * 0xffffff);
this.graphics.drawCircle(10, 10, 10);
this.graphics.endFill();
}
/**随机出现在舞台中*/
public function calculatePosition() : void {
if(parent && parent.stage)
{
this.x = Math.random() * parent.stage.stageWidth;
this.y = Math.random() * parent.stage.stageHeight;
}
}
/**从父容器中移除*/
public function removeSelf() : void {
parent && parent.removeChild(this);
}
}
}
从代码中可以看出,Main类中的Timer对象有两个事件侦听器。分别对Timer对象的TimerEvent.TIMER和TimerEvent.TIMER_COMPLETE事件进行侦听,这两个侦听器函数中分别对Basketball对象的calculatePostiton()和removeSelf()存在引用。当Basketball对象从舞台中移除后,由于未对这两个侦听器进行解除注册,Timer对象内部的侦听列表仍然有对这两个侦听器的引用,也即对Basketball对象的calculatePostiton()方法和removeSelf()方法持有引用,最终导致Basketball对象不能彻底从内存中移除。正确的做法应该是当Timer对象抛出TimerEvent.TIMER_COMPLETE事件后移除对Timer对象的TimerEvent.TIMER和TimerEvent.TIMER_COMPLETE事件的侦听。
private function timerComplete(e : TimerEvent) : void {
timer.removeEventListener(TimerEvent.TIMER, onTimer);
timer.removeEventListener(TimerEvent.TIMER_COMPLETE, timerComplete);
basketball.removeSelf();
basketball = null;
}
转载于:https://blog.51cto.com/zoujiandong1988/784225