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;

}