Whats the appropriate form when dispatching events in AS3?
Asked Answered
P

3

2

I was wondering what the appropriate form was when creating custom events? Should one create a CustomEvent class, and then create a temporary dispatcher in the function, and dispatch the CustomEvent. or is it better to attempt to create a CustomEventDispatcher class, and create the CustomEvent class as an internal class of that class, eg:

package
{

   public class CustomEventDispatcher extends EventDispatcher
   {
     public function CustomEventDispatcher()
     {
       super(new CustomEvent());
     }

   }
}

class CustomEvent
{
   public function CustomEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
   {
      super(type, bubbles, cancelable)
   }                                               
}
Practicable answered 23/6, 2011 at 4:1 Comment(0)
C
0

There are two basic questions to answer, when conceiving event mechanics.

1) How do I create dispatcher instance for my events?

General options are: extend EventDispatcher, or aggregate dispatcher instance.

Most basic and common practice (and official docs also state that), is extending EventDispatcher class, thus giving your classes event-dispatching capabilities.

Pros: simple to implement -- just type extends EventDispatcher, and you are done.

Cons: you can't extend something else. Apparently, this is the reason why many native classes are EventDispatcher's grandchildren. Just to spare us the trouble, I guess.

Second general approach is aggregating a dispatcher instance.

package
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IEventDispatcher;

    public class ClassA implements IEventDispatcher
    {
        private var dispatcher:EventDispatcher;

        public function ClassA()
        {
            initialize();
        }

        private function initialize():void
        {
            dispatcher = new EventDispatcher(this);
        }

        public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
        {
            dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
        }

        public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
        {
            dispatcher.removeEventListener(type, listener, useCapture);
        }

        public function dispatchEvent(event:Event):Boolean
        {
            return dispatcher.dispatchEvent(event);
        }

        public function hasEventListener(type:String):Boolean
        {
            return dispatcher.hasEventListener(type);
        }

        public function willTrigger(type:String):Boolean
        {
            return dispatcher.willTrigger(type);
        }
    }
}

Note: we pass a reference to aggregating class to dispatcher constructor. This is done to make event.target reference your class instance and not the dispatcher instance itself.

Pros: you are free to extend whatever you like. You may do some tricks with dispatcher hooks like maintaining listeners list or something alike.

Cons: not as simple as the first approach.

2) How do I pass custom data with my events?

General options are: pass data in an event instance, or only use event.target reference in event handler to access some data from source.

If you choose to access all necessary data through event.target -- no additional work nedded, just cast this reference in event handler to appropriate class.

If you want to pass some data along with event, you subclass Event, and this class should be publicly visible to the code that handles events, as the answer above states. AS3 is all about strict and strong typing, so why would you resist that?

Overriding clone() method in an Event subclass is only necessary if you are going to redispatch handled events. The official docs say you must do that every time you create a custom event class, just to be safe.

Countrydance answered 23/6, 2011 at 14:37 Comment(2)
All were good answers, but the clarity and relatively thorough response here was my favorite. Plus the simple pro-con approach didn't hurt either. Thank you very much. Also, did you use the private function call in the constructor for JIT optimization purposes?Practicable
Well, I always do initialization stuff in a separate function. It's not all about compiler not optimising constructor code: it makes your code more flexible, since you can defer calling init method.Countrydance
W
2

Unilaterally, it is better to make events publicly accessible. This way you can type your listeners (good for code hinting and debugging) and have the Event have public static const types (which you also may want to look in to).

Walterwalters answered 23/6, 2011 at 4:21 Comment(0)
P
0

don't forget to override clone. it's also a good idea to override toString for debugging.

here's an example of one of my custom events:

package com.mattie.events
{
//Imports
import flash.events.Event;

//Class
public class SearchFieldEvent extends Event
    {
    //Constants
    public static const SEARCH_COMPLETE:String = "search complete";

    //Variables
    public var totalResults:uint;
    public var duration:uint;
    public var searchText:String;

    //Constructor
    public function SearchFieldEvent(type:String, totalResults:uint = 0, duration:uint = 0, searchText:String = "") 
        {
        super(type);

        this.totalResults = totalResults;
        this.duration = duration;
        this.searchText = searchText;
        }

    //Override clone
    public override function clone():Event
        {
        return new SearchFieldEvent(type, totalResults, duration, searchText);
        }

    //Override toString
    public override function toString():String
        {
        return formatToString("SearchFieldEvent", "type", "totalResults", "duration", "searchText");
        }
    }
}
Precincts answered 23/6, 2011 at 5:46 Comment(0)
C
0

There are two basic questions to answer, when conceiving event mechanics.

1) How do I create dispatcher instance for my events?

General options are: extend EventDispatcher, or aggregate dispatcher instance.

Most basic and common practice (and official docs also state that), is extending EventDispatcher class, thus giving your classes event-dispatching capabilities.

Pros: simple to implement -- just type extends EventDispatcher, and you are done.

Cons: you can't extend something else. Apparently, this is the reason why many native classes are EventDispatcher's grandchildren. Just to spare us the trouble, I guess.

Second general approach is aggregating a dispatcher instance.

package
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IEventDispatcher;

    public class ClassA implements IEventDispatcher
    {
        private var dispatcher:EventDispatcher;

        public function ClassA()
        {
            initialize();
        }

        private function initialize():void
        {
            dispatcher = new EventDispatcher(this);
        }

        public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
        {
            dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
        }

        public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
        {
            dispatcher.removeEventListener(type, listener, useCapture);
        }

        public function dispatchEvent(event:Event):Boolean
        {
            return dispatcher.dispatchEvent(event);
        }

        public function hasEventListener(type:String):Boolean
        {
            return dispatcher.hasEventListener(type);
        }

        public function willTrigger(type:String):Boolean
        {
            return dispatcher.willTrigger(type);
        }
    }
}

Note: we pass a reference to aggregating class to dispatcher constructor. This is done to make event.target reference your class instance and not the dispatcher instance itself.

Pros: you are free to extend whatever you like. You may do some tricks with dispatcher hooks like maintaining listeners list or something alike.

Cons: not as simple as the first approach.

2) How do I pass custom data with my events?

General options are: pass data in an event instance, or only use event.target reference in event handler to access some data from source.

If you choose to access all necessary data through event.target -- no additional work nedded, just cast this reference in event handler to appropriate class.

If you want to pass some data along with event, you subclass Event, and this class should be publicly visible to the code that handles events, as the answer above states. AS3 is all about strict and strong typing, so why would you resist that?

Overriding clone() method in an Event subclass is only necessary if you are going to redispatch handled events. The official docs say you must do that every time you create a custom event class, just to be safe.

Countrydance answered 23/6, 2011 at 14:37 Comment(2)
All were good answers, but the clarity and relatively thorough response here was my favorite. Plus the simple pro-con approach didn't hurt either. Thank you very much. Also, did you use the private function call in the constructor for JIT optimization purposes?Practicable
Well, I always do initialization stuff in a separate function. It's not all about compiler not optimising constructor code: it makes your code more flexible, since you can defer calling init method.Countrydance

© 2022 - 2024 — McMap. All rights reserved.