AS3 EventManager Class: removeAllListeners
Posted on July 2nd, 2008 in Actionscript 3.0, OOP |
I heard about a class that Grant Skinner wrote called Janitor that was supposed to help keep track of listeners, but I couldn’t find it. Consequently, I wrote my own “EventManager” class for a gaming project I’m working on which keeps track of Event listeners in a project.
As all Actionscript 3 developers know, one of the biggest annoyances is keeping track of listeners and ensuring objects are collected in memory. This class does a lot of that for you, and even has a method removeAllListeners which has different filters. So let’s say some listener keeps calling a function, you can remove all listeners that point to that function. Or let’s say you want to remove ALL key listeners.
Here it is:
*EDIT 9/30/08: EventManager Updated. Click here to get it.
For example, let’s say you have something like so:
var obj:MovieClip = new MovieClip(); var obj2:MovieClip = new MovieClip(); obj.addEventListener(Event.ENTER_FRAME,Test,false,0,true); obj = obj2; obj.removeEventListener(Event.ENTER_FRAME,Test); // Does NOTHING!
Test will still be called every frame! Even though weak reference is set to true and there are no more references to obj! This is not good! But with EventManager…
var obj:MovieClip = new MovieClip(); var obj2:MovieClip = new MovieClip(); EventManager.addEventListener(obj,Event.ENTER_FRAME,Test,false,0,true,true); // last parameter actually adds the listener, see documentation in class of why this last parameter exists. obj = obj2; // Now we have a bunch of options, any of the bottom lines would work EventManager.removeAllListeners(null,Event.ENTER_FRAME); // will remove all Event.ENTER_FRAME listeners EventManager.removeAllListeners(null,Event.ENTER_FRAME, Test); // will remove all Event.ENTER_FRAME listeners that call Test EventManager.removeAllListeners(null,null, Test); // will remove all listeners that call Test EventManager.removeAllListeners(); // will remove all listeners
The only problem with the class is that this version does not distinguish useCapture events… But big deal. Maybe I’m naive, but how often does anyone actually set useCapture to true?
Anyway, if this class gets a lot of attention I’ll put it as open source on Google Code. Then someone else can add in functionality for useCapture.
This class was such a pain to code. AS3’s Dictionary is the only sure fire way to index objects as objects (as Array uses the result of toString() for indexes), but because (for some reason that’s beyond me), Adobe decided not to have a length property in Dictionary, my life was made very difficult. There might be some bugs, but based on my initial tests everything seems to be working fine. I wonder how Grant’s Janitor class is compared to mine. I really couldn’t figure out any other way to write the function definitions for EventManager.addEventListener and EventManager.removeEventListener (having actuallyAddListener and actuallyRemoveListener as the last parameter). I wish AS3 had a way to get the memory location value of an object. Something like Object.toMemoryString or something. That way Arrays could be used and the Object.toMemoryString value (which would be unique for every single object) could be used as keys.
If you decide to use this class, please let me know so I know my work hasn’t been in vain!
8 Responses
I’m not entirely certain I released the Janitor class… I’ll have to check and release it if not. It also makes extensive use of weakly referenced dictionary objects.
Just for the record, it’s “Grant”, though “Grank” would be a pretty interesting name.
Doh, that was a typo.
Great class. Even though using weak references is mostly sufficient, I like the ‘removeall’ function just for the convenience.
Do you mind if I extend it slightly to support passing of 1-2 variables ? Sometimes it can be very handy to pass params via events.
thanks!
Erik,
Weak references are sometimes efficient; however, they don’t always work (see example in post).
I have no problem of anyone extending the class; I could even post it on google code if anyone else wants to contribute to it.
Danny - Thanks. This is exactly what I have been searching for! I’ve got lots of vendors that aren’t cleaning up listeners very well….
The Janitor Class can be found in the source files included with this presentation: http://gskinner.com/talks/resource-management/
Super useful class. I do a lot of work loading files from animators that love ENTER_FRAME in nested MovieClips. It’s gotten to the point where a lot of times with AS3 I am reloading the player just to avoid the cleanup that is involved in getting these files out of the player. Being able to hand them something like this off so that I can keep track of their stuff in the shell is invaluable. Thanks for putting it up there.
note removeAllListeners
var observers:Array = (temp as Array).slice( 2 );
while( observers.length > 0 )
{
removeEventListener(temp[0], temp[1], observers[0], false );
observers = Arrays.removeAt(observers, 0);
}