ActionScript: Removing Event Listeners

I came across an interesting problem the other day with regards to AS3 garbage collection. I assumed that when an object is removed from the stage, everything is removed, including event listeners. This is not the case. I created a carousel class for my new portfolio site. The carousel displays images for a specific portfolio category (web, business cards, magazines, etc). When the user clicks a link for a different category, all images for the current category are removed and then the new images are loaded. But when the new images loaded, I received the error:

?View Code ACTIONSCRIPT
Error #1009: Cannot access a property or method of a null object reference.

After some testing, I found that the event listeners were not being removed.

Remove Objects

When a user clicks on a category link, the following method is called in my Document Class.

?View Code ACTIONSCRIPT
private function removeAllChildren():Boolean {
	while (this.numChildren > 0) {
		this.removeChildAt(0); 
	}
	return true;
}

Note: I discuss this method in a bit more detail in this post.

The carousel class is then instantiated with a new list of images:

?View Code ACTIONSCRIPT
var xGal:XMLList = aPortfolio[category];
var g:gp3DCarousel = new gp3DCarousel(xGal, 360, 20);

The Problem – Error #1009

Once the carousel class is instantiated, I load each image in a MovieClip. I then create a few event listeners.

?View Code ACTIONSCRIPT
private function startCarousel():void {
        for (var i = 0; i < _total_images; i++) {
                _mc = MovieClip(  thumb_cntr.getChildByName("image_thumb_" + i ) );
                _mc.addEventListener( MouseEvent.CLICK, onMouseClick );
                _mc.addEventListener( Event.ENTER_FRAME, onFrameEnter ); 
                ...
        }
}

Error #1009 occurs on the ENTER_FRAME event (onFrameEnter). Apparently this event is not removed when the class is removed from the stage.

The Solution – Event.REMOVED_FROM_STAGE

So I added a REMOVED_FROM_STAGE event.

?View Code ACTIONSCRIPT
private function startCarousel():void {
        for (var i = 0; i < _total_images; i++) {
                _mc = MovieClip(  thumb_cntr.getChildByName("image_thumb_" + i ) );
                _mc.addEventListener( MouseEvent.CLICK, onMouseClick );
                _mc.addEventListener( Event.ENTER_FRAME, onFrameEnter ); 
                _mc.addEventListener(Event.REMOVED_FROM_STAGE, removeEvents, false, 0, true);
                ...
        }
}
 
protected function removeEvents(e:Event):void {
	e.target.removeEventListener( Event.ENTER_FRAME, onFrameEnter );
	e.target.removeEventListener( MouseEvent.CLICK, onMouseClick );
}

Now when I call removeAllChildren and the carousel is removed from the stage, the event listeners for each MovieClip image are removed as well.

Be Sociable, Share!

Checkout My New Site - T-shirts For Geeks