Implementing IEventDispatcher

english mobile

Recently, I had to have a class that took arguments in its constructor and also was able to dispatch events. Rather than trying to extend EventDispatcher and worry about separating the arguments the rest of the class needed from the ones EventDispatcher needed, I decided to implement IEventDispatcher. Problem was, I hadn't done this in a while, and I couldn't remember the right way to do this and had no idea what project had an example of it. So, I went searching on the web and refreshed my memory that you need to include an EventDispatcher instance in your class and route your IEventDispatcher methods through that object.

I created some boilerplate code that I can just cut and paste to add IEventDispatcher support to a class, and I share it with you now.



//--------------Support for IEventDispatcher--------------//


private var _ed:EventDispatcher;

public
function addEventListener(type:String, listener:Function,
useCapture:Boolean=false, priority:int=0,
useWeakReference:Boolean=false):void
{
_ed.addEventListener(type,
listener, useCapture, priority, useWeakReference);
}
public function
removeEventListener(type:String, listener:Function,
useCapture:Boolean=false):void
{
_ed.removeEventListener(type, listener,
useCapture);
}
public function
dispatchEvent(event:Event):Boolean
{
return
_ed.dispatchEvent(event);
}
public function
hasEventListener(type:String):Boolean
{
return
_ed.hasEventListener(type);
}
public function
willTrigger(type:String):Boolean
{
return _ed.willTrigger(type);
}



Enjoy!

Updated 12/15/08:
Note that you'll need to put an instance of EventDispatcher in _ed in the constructor of the class that's implementing IEventDispatcher:

_ed=new EventDispatcher(this);

Updated 12/21/08:
Josh McDonald posted code that shows how to implement IEventDispatcher with boilerplate that doesn't require adding a line to the constructor.

8 comments:

harley said...

Hi:
I am actually trying to just load an xml from a url and working with flex builder 3... and pretty much a beginner.. but stumbled on to the adobe example.. URLLoaderExample.as

this extends sprite... and .. the code is:
**********************start

package {
import flash.display.Sprite;
import flash.events.*;
import flash.net.*;

public class URLLoaderExample extends Sprite {
public function URLLoaderExample() {
var loader:URLLoader = new URLLoader();
configureListeners(loader);

var request:URLRequest = new URLRequest("urlLoaderExample.txt");
try {
loader.load(request);
} catch (error:Error) {
trace("Unable to load requested document.");
}
}

private function configureListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.COMPLETE, completeHandler);
dispatcher.addEventListener(Event.OPEN, openHandler);
dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}

private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
trace("completeHandler: " + loader.data);

var vars:URLVariables = new URLVariables(loader.data);
trace("The answer is " + vars.answer);
}

private function openHandler(event:Event):void {
trace("openHandler: " + event);
}

private function progressHandler(event:ProgressEvent):void {
trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
}

private function securityErrorHandler(event:SecurityErrorEvent):void {
trace("securityErrorHandler: " + event);
}

private function httpStatusHandler(event:HTTPStatusEvent):void {
trace("httpStatusHandler: " + event);
}

private function ioErrorHandler(event:IOErrorEvent):void {
trace("ioErrorHandler: " + event);
}
}
}


----------stop

what's the reason to implement IEventDispatcher?
the stub code generated for implementing the IEventDispatcher seemed pretty concise. it provided a function to add the event listener as well as to remove it. which seems to me be a good idea to save memory I assume.

although, it didn't seem to add any of the error handling shown as shown in the above example. Below is the stub code.

Had I not of decided to try and implement this (in flex builder 3) I might have just used the example.. and not have considered the other functions to consider.



***********start

package com.adobe.example
{
import flash.events.Event;
import flash.display.Sprite;
import flash.events.IEventDispatcher;

public class URLLoaderExample extends Sprite implements IEventDispatcher
{
public function URLLoaderExample()
{
//TODO: implement function
super();
}

public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
{
//TODO: implement function
}

public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void
{
//TODO: implement function
}

public function dispatchEvent(event:Event):Boolean
{
//TODO: implement function
return false;
}

public function hasEventListener(type:String):Boolean
{
//TODO: implement function
return false;
}

public function willTrigger(type:String):Boolean
{
//TODO: implement function
return false;
}

}
}

---------stops

I can see if I am extending another class/object (Sprites a class at this point right?) I can't extend two classes...
So in general terms, when would it be important to implement IEventDispatcher?

the example above... didn't think it was important enough to implement. but this might be for the sake of the example...

and I guess can you tell me what is specifically going on when "implementing" another class..
Thanks!

Amy B said...

In the first example, the configureListeners function is being used internally by URLLoaderExample to add listeners to its internal URLLoader, which is already an event dispatcher (note the argument definition calls for an IEventDispatcher as an argument). Note that Sprite also already extends EventDispatcher.

In your second example, Flex will paste in empty properties and methods that an interface calls for when you create a new class that implements any interface, even one you wrote yourself. It's up to you as a developer to add the content. The post you were commenting on was to provide that content, since I didn't find it intuitive or obvious to figure out what it was.

You extend EventDispatcher or implement IEventDispatcher when your object can't natively dispatch events. More often than not, these will be pure data objects (value objects). If my object doesn't need arguments in its constructor, quite often I'll just extend EventDispatcher. This is because EventDispatcher already has an argument in its constructor, and if someone inherits your code and you use different arguments in the constructor than the object you're extending, it might confuse them. If the object is already written and needs to dispatch events, that's another place where I'll just implement IEDispatcher.

harley said...

thank you for helping me understand this and also for showing how to implement IEventDispatcher.

so for a class that extends a sprite.. there isn't a need to "implement" IEventDispatcher since it already inherits EventDispatcher which is defined by the interface of IEventDispatcher. Because, the sprite by design, has registered the functions in the "stub" code i posted already.. no need to implement this, right?

So, how would I recognize the situation that calls for the implementation of IEventDispatcher?

in my case, is it enough to simply import flash.events.IEventDispatcher then configure listeners?

and, in cases where an extension of a class doesn't include EventDispatcher or IEventDispatcher, is it enough to import flash.events.IEventDispatcher to be able to make calls like RemoveEventListener, AddEventListner, etc.?

I don't completly understand why i need to register these functions through implementation.

Amy B said...

If you're using any class that inherits any class that either is an EventDispatcher or has an EventDispatcher (in which case it will implement IEventDispatcher or inherit from a class that implements IEventDispatcher.

To understand why you have to "fill in" the blank methods of an Interface, you need to understand what an Interface is. If the link that I posted in my last comment to the LiveDocs explanation of interfaces didn't give you enough detail, I'd suggest you pick up the book ActionScript 3 Design Patterns and at least read the first couple of chapters.

harley said...

rats... i see it, on page 33. oh...I'm starting to get it.. thanks. that's a great recommendation.
not so easy to explain either.. this is a great book.. I am so glad I have it.

Thanks again for starting this post, it really helped.

I'll keep a link on this.

Martin Harrigan said...

Thank you! Reminds me of the decorator design pattern - useful when you don't want to use up your single inheritance with EventDispatcher ;-)

RBlinzler said...

Like harley, I'm trying to dispatch a custom event from another class that already implements IEventDispatcher - in this case a MovieClip.
Until I read this blog post, I kept getting an error of '1024: Overriding a function that is not marked for override' and didn't realize that MovieClip already implemented EventDispatcher.
I'm having trouble bridging the gap between harley's example and dispatching a custom event in my MovieClip, can anyone point me to another example of this?
Thank you.

Amy B said...

Maybe http://flexdiary.blogspot.com/2007/08/dispatching-events.html will help. If not, maybe http://cookbooks.adobe.com/post_Building_custom_events_we_can_verify_specific_oper-17609.html.