3 ways to solve the “I want to call an event handler function directly” problem

< back to overview

Say you have an event handler that is called each time an event is triggered and you would like to call this function directly (so without waiting for an event to happen). See the following scenario of a ticking clock to make this more clear:

-          TimerEvent that changes the rotation of the clock handlers.

-          The first time the screen has to be drawn, the timer is not yet in play mode. Because when the timer interval is set to 1 second, the first frame would only be drawn after the first second has ticked away.

Normally you would do the following:

-          Create the timer, listener and addEventListener

-          Call the listener function directly

-          Argument Count Error, since event listeners always require an event Object being passed. And since it’s not always opportune

Or in code:

public function Clock()

{

      tmr = new Timer(1000, 0);

      tmr.addEventListener(TimerEvent.TIMER, timer_tick);

      tmr.start();

 

      timer_tick();  // Argument Count Mismatch Error! A timerEvent object should be provided.

}

private function timer_tick(ev:TimerEvent)

{

      // Do something

}


You could however write another initialize function to set up your scene, but sometimes it’s just quicker to directly call event handlers. Especially in a debugging context.

Solution 1 (write extra function):

Create a separate function, say rotate_handles, without any arguments that does the rotation. Both the first frame call and the timer_event handler function call this function in their body.

public function Clock()

{

      // timer init (see above)

      rotate_handles();

}

private function timer_tick(ev:TimerEvent):void

{

      rotate_handles();

}

private function rotate_handles():void

{

      // Do something

}


Solution 2 (Optional Event object):

Make the Event property that the timer_event functions receives an optional parameter:

public function Clock()

{

      // timer init (see above)

 

      timer_tick(); // timerEvent is now optional so we don’t need to pass this.

}

private function timer_tick(ev:TimerEvent = null)

{

      // If necessary you can check if timerEvent is provided by using the following syntax:

      if (ev != null)  

      {

            // TimerEvent is passed

      }

 

      // Do something

}


Of course this can also be achieved by passing a null value to the method call, which brings me to…

Solution 3 (Pass null to handler):

if you pass a null value to an event handler. The event object will simply be null but flash will see this as a valid argument.

public function Clock()

{

      // timer init (see above)

      timer_tick(null); // pass a null value to the event handler

}

private function timer_tick(ev:TimerEvent)

{

      // If necessary you can check if timerEvent is valid (not null) by using the following syntax:

      if (ev != null)  

      {

            // TimerEvent is valid

      }

 

      // Do something

}
This way you can call this function from anywhere without providing a valid TimerEvent object and not having to write a separate function.

  • Share/Bookmark
< back to overview

Comments

Marc Hughes on March 2, 2009 at 5:37 pm

Solution #1 is probably the more “correct” way of doing it, but I tend to pick solution #3 since it’s the quickest/easiest way.

But I name my function a little different. I’d have

protected function rotate_handles(event:Event = null):void
{
// Do something
}

I prefer calling the method by what it does instead of by what it will be triggered by.


Marc Hughes on March 2, 2009 at 5:38 pm

Aw crud, I meant I usually do #2, not #3


Eric Cancil on March 2, 2009 at 11:08 pm

I tend to not like putting any application logic within event handlers. Not only does this make unit testing a lot easier, but you also avoid problems like this someHandler(e:Event = null) where you’re either leaving the event default null….or doing some kind of check in the function.


Martial Clausse on March 10, 2009 at 6:25 pm

There is a 4th solution,

public function Clock(){
tmr = new Timer(1000, 0);
tmr.addEventListener(TimerEvent.TIMER, timer_tick);
tmr.start();
tmr.dispatchEvent(new TimerEvent(TimerEvent.TIMER));
}

private function timer_tick(ev:TimerEvent):void{
// Do something
}

private function timer_tick(ev:TimerEvent):void{
// Do something
}

That way you don’t have to check if the event you receive is null or not since you force your timer to dispatch the event, and you are sure that your eventHandler have everything it needs to work…


alwyn on March 12, 2009 at 5:44 pm

Hi Martial. This is indeed another option but my goal was to not create an event myself. Since events can sometimes be tricky to construct yourself.
Thx for the input!


Make a comment