Macromedia’s EventDispatcher class is used in almost every one of my Flash projects, and it’s the foundation for my component framework. Obviously, I find it’s functionality indispensable. However, it comes with limitations that I’d like to live without. For one, specifying a function name to call in a listener could be simpler. Delegate is useful, but having to use it for almost every event call makes it’s functionality a good candidate for encapsulation. I’ve also never been a big fan of the event object the listener receives as an argument. It uses Flash’s dynamic typing, which I admit can be useful at times. However, events tend to have uniform arguments, so I’d like it to be a little more type-safe. Ideally, I’d like the listener to receive these arguments like a regular function. With so many needs, I realized it was time to get down and dirty with events.
On a side note, I’d like events in other Macromedia classes to behave the same way. I usually have to check the documentation to remember which way to listen to a particular object. With some classes, you can only listen to all the events at once, and in others, there’s a specific function in the object that you have to implement, which will then be in that object’s scope. You’ll then have to hack your way out to access variables and methods in another object. Of course, I can’t replace the system used by some of these classes, they’re hardcoded into the player, but it’s not too hard to create a wrapper class that hides the clutter and utilizes my new event model to keep everything consistent.
This new event model involves two main classes: Event and EventManager. Event handles one specific event by keeping track of the listeners for that event and dispatching to them as requested. It works behind the scenes as part of EventManager. EventManager is the front end that acts as a repository for events. Every one of my components has one. It’s simple to add an event, then pass on any objects that want to listen to a specific event. Here’s a basic example of how a component sets up its EventManager:
import net.zeusdesign.events.EventManager; class SomeComponent { private var _eventManager:EventManager; function SomeComponent() { //instantiate the event manager this._eventManager = new EventManager(); //the event is then added to the manager this._eventManager.addEvent("onSomeEvent"); } public function get eventManager():EventManager { //It's easier for outside classes to listen to the EventManager //directly, so we don't have to implement add and remove methods //over and over. return this._eventManager; } public function someClassMethod(arg1, arg2):Void { //now, somewhere else in the class, I want to dispatch the event this._eventManager.dispatchEvent("onSomeEvent", [arg1, arg2]); } }
An object that wants to listen to an event, can do so easily. You’ll notice I added a third argument to the standard addEventListener. I call this the routing function. This argument allows a listener to specify a specific function to call when the event is triggered. It can be very useful if you have many components that would normally have the same event name. Also, as you saw above, events are passed as an Array to EventManager, but when the event is triggered, the listener function receives arguments like a normal function instead of one event object like EventDispatcher.
var c:SomeComponent = new SomeComponent(); c.eventManager.addEventListener("onSomeEvent", this, "onCustomEventName"); function onCustomEventName(arg1, arg2):Void { //do something }
You can download the EventManager source code now. If you have any questions, comments, or improvements please leave a comment below.