A Flash Developer Resource Site

Results 1 to 12 of 12

Thread: [RESOLVED] Dispatch and Listen for a Global Event

  1. #1
    Senior Member
    Join Date
    Jan 2006
    Posts
    133

    resolved [RESOLVED] Dispatch and Listen for a Global Event

    All,

    Thanks for your patience, I know there's been quite a few posts about events, but I've run into a problem that I haven't really encountered before, and I've kind of confused myself with all the talk of "bubbles" and "capture" and various complexities of creating custom events, etc...

    Anyway, I'm trying to figure out how to dispatch a global broadcast style of event.

    1) If I have a custom class that resides in the Display List (the DispatcherClass), how do I set up this class to broadcast a "global" event?

    Actionscript Code:
    dispatchEvent(new Event()); // help me fill this out

    1b) If I have another custom class that also resides in the Display List (but in a completely unrelated heirarchy), how do I get this ListenerClass to "hear" the event WITHOUT explicitly referencing the instance of the DispatcherClass like so:
    Actionscript Code:
    DispatcherClassInstance.addEventListener("DispatcherClassEvent", handler, false, 0, true);

    Is this even possible?


    =======

    2) What if the DispatcherClass DOES NOT reside in the DisplayList?
    Is it possible to dispatch a "global" style event since there is nothing to "bubble" up through?

    2b) How would I get a ListenerClass, maybe on the DisplayList, maybe not, to "hear" this event?

    So confused...

  2. #2
    Senior Member jweeks123's Avatar
    Join Date
    Mar 2006
    Posts
    1,124
    Code:
    dispatchEvent(new Event("DispatcherClassEvent", true));
    
    addEventListener("DispatcherClassEvent", doThisFunction);
    
    function doThisFunction(evt:Event):void {
         trace("Woo Hoo");
    }

  3. #3
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    The built in event system does not include a "broadcast" functionality. But you can pretty easily build one yourself by making a single instance to dispatch your events.

    Code:
    public class Broadcaster extends EventDispatcher {
      private var _instance:Broadcaster = null;
    
      //DO NOT USE THIS.  Use static methods broadcastEvent and addBroadcastListener instead
      public function Broadcaster(){
        if (_instance != null){
           throw new IllegalOperationError("Broadcaster constructor called more than once");
        }
      }
    
      private static getInstance():Broadcaster{
        if (null == _instance){
           _instance = new Broadcaster();
        }
        return _instance;
      }
    
      public static broadcastEvent(event:Event):void{
        getInstance().dispatchEvent(event);
      }
    
      public static addBroadcastListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
        getInstance().addEventListener(type, listener, useCapture, priority, useWeakReference);
      }
    
    }
    Then you can register a listener from anywhere:
    Code:
    Broadcaster.addBroadcastListener("someEvent", somehandler);
    And trigger dispatch from anywhere
    Code:
    Broadcaster.broadcastEvent(new Event("someEvent"));

  4. #4
    Senior Member
    Join Date
    Jan 2006
    Posts
    133
    Quote Originally Posted by jweeks123 View Post
    Code:
    dispatchEvent(new Event("DispatcherClassEvent", true));
    
    addEventListener("DispatcherClassEvent", doThisFunction);
    
    function doThisFunction(evt:Event):void {
         trace("Woo Hoo");
    }
    Just changing "bubbles" to true doesn't seem to work. At least not with objects outside of the dispatcher's display list hierarchy. Using the above I could "hear" the event in the dispatcher's parents... but not in the dispatcher's 3rd cousins twice removed.


    Quote Originally Posted by 5TonsOfFlax View Post
    The built in event system does not include a "broadcast" functionality. But you can pretty easily build one yourself by making a single instance to dispatch your events.
    Thanks, I've used classes like that with static functions before, don't know why it didn't occur to me to make a Broadcaster like that. Mainly I've used them to store utility functions that I use frequently, like truncating text, or generating random numbers, etc. The chief benefit, for me, was that instead of something like:

    Actionscript Code:
    var myUtilFunctions:UtilFunctions = new UtilFunctions();
    myUtilFunctions.someFunction();

    I could just:
    Actionscript Code:
    UtilFunctions.someFunction();

    In fact, you essentially tell me the same by noting "//DO NOT USE THIS." in regards to the constructor.
    but, there are a couple of nuances in your code I don't quite understand.

    1) I'm used to seeing the word "function" after "static", is that a typo? Or are getInstance(), broadcastEvent() and addBroadcastListener() not what I know as methods?

    2) What is the benefit/purpose to the getInstance() method? The Broadcaster class could be used "instance-less" couldn't it? Why use one of these over the other:
    Actionscript Code:
    public static broadcastEvent(event:Event):void{
        getInstance().dispatchEvent(event);
    }

    public static broadcastEvent(event:Event):void{
        dispatchEvent(event);
    }

    ps. Those utility classes I had created before never extended anything... since they really had no higher functionality than as a storage area for functions. So does extending an actual class (i.e. EventDispatcher) needs to be handled differently?

  5. #5
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    1. That's my mistake. "function" should be there. Too much Java lately.
    2. No, Broadcaster cannot be used "instanceless" because you need an actual EventDispatcher to dispatch events. That instance could have been a bare EventDispatcher, but you need something. If a bare EventDispatcher were used, the class would not need to extend anything.

    The semi private constructor and _instance variable are used to implement a singleton pattern.

  6. #6
    Senior Member
    Join Date
    Jan 2006
    Posts
    133
    Quote Originally Posted by 5TonsOfFlax View Post
    2. No, Broadcaster cannot be used "instanceless" because you need an actual EventDispatcher to dispatch events. That instance could have been a bare EventDispatcher, but you need something. If a bare EventDispatcher were used, the class would not need to extend anything.
    Ahh, ok, that makes sense... that you need an instance to dispatch the event... and I really only want 1 instance at any given time.

  7. #7
    Senior Member
    Join Date
    Jan 2006
    Posts
    133
    Got a compile error... _instance should be "static" as well, I think.
    Actionscript Code:
    private static var _instance:Broadcaster = null;

  8. #8
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Yes, you're right. I apologize for not trying to compile it before posting.

  9. #9
    Senior Member
    Join Date
    Jan 2006
    Posts
    133
    Quote Originally Posted by 5TonsOfFlax View Post
    Yes, you're right. I apologize for not trying to compile it before posting.
    Meh, no problem, that's what the Compiler Panel is for! The tricky part is when nothing works and you DON'T get errors =)

    I was just posting for completeness for future viewers.

  10. #10
    Senior Member
    Join Date
    Jan 2006
    Posts
    133
    Oops... not done yet apparently...

    Now I'm encountering an interesting problem when I try to remove the listeners.

    In ClassA (the dispatcher) I have:
    Actionscript Code:
    Broadcaster.broadcastEvent("someEvent");

    This line within ClassA is associated with an interval, so it basically tells the Broadcaster class to broadcast a "someEvent" event once a second.

    In ClassB (the listening class) I have:
    Actionscript Code:
    // in ClassB constructor
    Broadcaster.addBroadcastListener("someEvent", onSomeEvent, false, 0, true);

    // ClassB methods
    private function onSomeEvent(e:Event):void{
        trace("Broadcast Received");
    }

    This all works great. I get "Broadcast Received" traced to output panel about once a second.
    However, now I'm concerned with what happens when I want to destroy a ClassB instance and (hopefully) flag it for garbage collection. So, each instance of ClassB has a kill() method (called when it is removed from stage via removeChild) designed to remove "standard" listeners, children and other sub-processes to make sure that there aren't any extraneous references.
    Now, I have removed the ClassB instance from the Display List, and set all external/parent references to the ClassB instance to "null"; however, I'm still getting "Broadcast Received" traced to the output panel... even though ClassB instance that has the trace() script in it has been "destroyed".
    I thought that would easily be solved by removing the broadcast listener:
    Actionscript Code:
    public function kill():void{
        Broadcaster.removeEventListener("someEvent", onSomeEvent, false);
    }

    I got a strange compile-time error:
    Code:
    1061: Call to a possibly undefined method removeEventListener through a reference with static type Class.
    This threw me for a loop because Broadcaster extends EventDispatcher, so shouldn't it inherit the removeEventListener() method? Is there some reason I would need to override the EventDispatcher method?

    Or, do I need to create a special removeBroadcastListener() method in Broadcaster in order to remove any listeners added? If so, what would that look like??

    Thanks!

  11. #11
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Broadcaster does extend EventDispatcher, but removeEventListener is not a static method so it cannot be called on the Broadcaster class. It must be called on the broadcaster instance. I'd create that removeBroadcastListener method. Just have it pass through to the instance's removeEventListener method.

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

  12. #12
    Senior Member
    Join Date
    Jan 2006
    Posts
    133
    Quote Originally Posted by 5TonsOfFlax View Post
    Broadcaster does extend EventDispatcher, but removeEventListener is not a static method so it cannot be called on the Broadcaster class. It must be called on the broadcaster instance. I'd create that removeBroadcastListener method. Just have it pass through to the instance's removeEventListener method.
    Oy... should've known that... thanks!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center