I have been thinking about the useWeakReference argument in IEventDispatcher’s addEventListener() method. I feel like I don’t really trust it – see Joe Berkovitz’ post from last year – and also that a lot of the time, it’s not doing the job I want.
I often find that the only thing preventing an object in memory is the reference from a listener. As time goes on, I tend to prefer more concise code, so long as it still makes sense at a glance. There’s no point, it seems to me, setting an object property when the only use you will make of it is in an event handler method.
For instance, in a simple video-browsing app I am currently working on, I instantiate a data loader in the contructor, like this:
new DataSource(DATA_URL).addEventListener(Event.COMPLETE,
handleDataEvent);
I could of course use an object property to store the DataSource object. But I don’t want to, if I don’t have to. It would clutter the class. I can simply refer to event.target in the event handler method.
Now, I don’t want the DataSource object to hang around forever. As soon as Event.COMPLETE is dispatched and handled, I’m done with it (in this case). This might seem like a good occasion for useWeakReference=true. But it isn’t. Until Event.COMPLETE is dispatched, the garbage collector must not touch my DataSource object. I need a strong reference to keep it alive.
Of course I could call removeEventListener(). But that’s exactly the kind of ugliness I wanted to avoid; I want fluid, expressive code, and removeEventListener() smacks of hideous memory management code like malloc() and free(). I want some way I can listen out for one event only, and then implicitly forget the dispatcher ever existed – and by doing so, in my example, it will soon no longer exist.
What would be perfect for these kinds of situations, which I come across very often, would be to have a method called addDisposableEventListener(). Like disposable contact lenses, it’s a single-use operation; a one night stand. No numbers in little red books: in the morning, it’s over. When dispatchEvent() is called, any disposable event listeners are dropped; normal ones are kept.
The problem is – how? EventDispatcher is a native class; although it can be extended, I don’t think I can access the array of listeners (or however they are stored). I guess I could keep a separate array of disposable event listeners, and override dispatchEvent() like this:
override public function dispathEvent(event:Event):Boolean {
var success:Boolean = super.dispatchEvent(event);
var listener:Object;
while (null != (listener = disposableListeners.pop())) {
removeEventListener(listener.type, listener.func, listener.useCapture);
}
return success;
}
Or I could skip EventDispatcher altogether and write my own implementation of IEventDispatcher … but I’d rather avoid wheel reinvention if possible.
I have knocked up a little DisposingEventDispatcher (crap name, better suggestions would be appreciated!) class and added it to my open source AS3 library (only in svn at present). Or you can just grab the class here.




Recent Comments