One of my favorite features of AS3 is the low-level inclusion of EventDispatcher in the AS3 framework. I do not miss the days of including EventDispatcher mix-ins in 80% of my classes in 100% of my projects. I especially like the additional features of the AS3 EventDispatcher: cancellation, custom event types (built in), preventDefault, event phases, etc.
However we have had several AS3 projects that have had a need for an EventDispatcher that is not instance-based. So, without further ado, here is an approach that we have used since our AS2 days:
package {
import flash.events.EventDispatcher;
public class MyClass {
protected static var disp:EventDispatcher;
public static function addEventListener(...p_args:Array):void {
if (disp == null) { disp = new EventDispatcher(); }
disp.addEventListener.apply(null, p_args);
}
public static function removeEventListener(...p_args:Array):void {
if (disp == null) { return; }
disp.removeEventListener.apply(null, p_args);
}
public static function dispatchEvent(...p_args:Array):void {
if (disp == null) { return; }
disp.dispatchEvent.apply(null, p_args);
}
// Other class code
}
}
Note that this differs from a Singleton approach, in that I didn’t want to force a user to extend EventDispatcher (plus I dislike getInstance()). Additionally, some of my fellow developers have noted that using the apply syntax instead of defining all the arguments with types is lazy. Since this runs through an actual EventDispatcher instance, and this class is just a proxy, I didn’t think they were necessary.
I hope someone out there finds this useful. Internally we use it quite often – and it seems to be the most reliable way to add static-access events to a class.
Update
Since I was scolded for not typing the arguments, here is an update, and a sample usage.
package {
import flash.events.EventDispatcher;
import flash.events.Event;
public class MyClass {
protected static var disp:EventDispatcher;
public static function addEventListener(p_type:String, p_listener:Function, p_useCapture:Boolean=false, p_priority:int=0, p_useWeakReference:Boolean=false):void {
if (disp == null) { disp = new EventDispatcher(); }
disp.addEventListener(p_type, p_listener, p_useCapture, p_priority, p_useWeakReference);
}
public static function removeEventListener(p_type:String, p_listener:Function, p_useCapture:Boolean=false):void {
if (disp == null) { return; }
disp.removeEventListener(p_type, p_listener, p_useCapture);
}
public static function dispatchEvent(p_event:Event):void {
if (disp == null) { return; }
disp.dispatchEvent(p_event);
}
// Public API that dispatches an event
public static function loadSomeData():void {
dispatchEvent(new Event(Event.COMPLETE));
}
}
} |
package {
import flash.events.EventDispatcher;
import flash.events.Event;
public class MyClass {
protected static var disp:EventDispatcher;
public static function addEventListener(p_type:String, p_listener:Function, p_useCapture:Boolean=false, p_priority:int=0, p_useWeakReference:Boolean=false):void {
if (disp == null) { disp = new EventDispatcher(); }
disp.addEventListener(p_type, p_listener, p_useCapture, p_priority, p_useWeakReference);
}
public static function removeEventListener(p_type:String, p_listener:Function, p_useCapture:Boolean=false):void {
if (disp == null) { return; }
disp.removeEventListener(p_type, p_listener, p_useCapture);
}
public static function dispatchEvent(p_event:Event):void {
if (disp == null) { return; }
disp.dispatchEvent(p_event);
}
// Public API that dispatches an event
public static function loadSomeData():void {
dispatchEvent(new Event(Event.COMPLETE));
}
}
}
MyClass.addEventListener(Event.COMPLETE, onComplete, false, 0, true);
function onComplete(p_event:Event):void {
trace("Complete!");
}
MyClass.loadSomeData(); |
MyClass.addEventListener(Event.COMPLETE, onComplete, false, 0, true);
function onComplete(p_event:Event):void {
trace("Complete!");
}
MyClass.loadSomeData();