Event-based architectures for Adobe Flex

I had a number of interesting conversations in the last few weeks with developers who were experiencing life-cycle issues in their Flex applications, especially when their apps were run on slower machines…or even smart phones. They eventually had figured out that there were certain places in their apps where they had hardcoded properties into Classes. And, when those properties weren’t initialized in the right order…the code block which requested those properties failed with null exception errors.

Since Flex doesn’t have threads we are dependant on the linear execution of the code, which just so happens to include MXML, ActionScript and occasionally JavaScript. That means, for the most part, that your code is executed one line at a time, in the order in which it was written. 

To give you an example of how this can go wrong: if you are expecting an MXML custom component to be initialized with all its properties populated, you’ll get null value exceptions if this hasn’t occurred when you try and display that custom component. And, when you look at in the debugger you’ll be astonished to see all your properties are null or uninitialized in some way.

The bottom-line is if you don’t understand the life-cycle of your app you could end up severely beating your head against a wall for hours (or days) trying to figure out what’s going wrong. I don’t know why, but Adobe doesn’t talk much about life-cycle. To me, it’s mission critical to understand it. If you want to build anything more than very simple applications, I gaurantee you’ll eventually have to deal with it. Now fortunately there are some excellent articles out there. I highly recommend this excellent PDF by DevelopmentArc. Read it!

I also recommend making your architectures more loosely coupled, and event-based, rather than expecting immediate results. It may seem counter-intuitive at first. What it means is you can tie your code together based on something that happens in the future. And, your app will wait until that event occurs, then it will proceed as directed and not a moment sooner. 

So what am I talking about? For example, if you make a request to a REST Web Service, you can assign an event dispatcher to fire off when the response payload has been received and an event listener somewhere else in your app will wait for that event to occur. Sometimes servers take a while to respond, or maybe the internet was slow, or maybe the smartphone temporarily had a bad cell connection. When that happens, it will delay when your app recieves the payload. Or if you don’t receive a payload back after a certain period of time, you can throw an error event. All these types of scenarios can be gracefully handled with built-in ActionScript events as well as custom events that you build.

What’s the alternative? If your application immediately asks for a result and the response payload got delayed, guess what? You’re app will fail or throw an error.

I also want to throw one more bone of caution your way. Events themselves are subject to what’s called propogation. You may not want to, but you really do need to read as much about propogation as you can! Once you have a basic understanding of both application life-cycle and propogation you will be able to build much more robust applications. And in the long run that translates to more time you can dedicate to watching basketball, football, or whatever else you want to do with your new found “free” time.

So, my suggestion is make judicious use of custom events. Here’s a short article from Adobe on how to do it.

References:

DevelopmentArc – Understanding the Adobe Flex® 3 Component and Framework Lifecycle

Adobe – Dispatching Custom Events

Adobe – Event Propogation

Best Practices for ActionScript Event Listeners

I see a lot of incorrect instantiation of event listeners, and I’ve also done it wrong quite a few times myself, especially when coding really fast. Doing it right is easy and the following four steps could save you a ton of debugging time later. 

Step 1: First, create the object. In this case I’m creating a Timer object using the ActionScript flash.utils.Timer Class:  

var myTimer:Timer = new Timer(1000);

Step 2: Second, always add your event listeners before executing any of the objects methods. And always, always attach the event listener to an object. Simply calling an addEventListener without attaching it to an object means the listener will receive any events broadcast for that type of event. This can become a nightmare in projects that may have dozens or even hundreds of event listeners running and you have to debug a problem. 

//myTimer is the object to which we will attach the listener.
//timer is the type of listener we want to observe.
//And, timerHandler the function to call when the event occurs.
myTimer.addEventListener(“timer”,timerHandler);

Step 3: Third, now you can call the objects method. I’m going to call the start() method which will kick off the Timer: 

myTimer.start();

Step 4: Lastly, when you are done with an object, always remove the event listener. Leaving event listeners active when they aren’t needed can cause memory leaks. If an object is not removed, it is still registered and it will remain in memory. By removing the event listener, you’ll allow the garbage collector to eventually deallocate it from memory. 

    myTimer.removeEventListener(“timer”,timerHandler);

Why do things in this order? If you add your event listeners after calling a method, such as start(), you can potentially miss an event that occurs right before the event listener is created. By only calling methods after event listeners are created you eliminate the possibility of missing something and banging your head against the wall while trying to debug it under a heavy deadline. 

Here’s a complete Flex 4 sample app that you can play with to try it out: 

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="https://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:mx="library://ns.adobe.com/flex/mx">
 <fx:Script>
     <![CDATA[   

       private var myTimer:Timer;

       public function timerHandler(event:TimerEvent):void
       {
          var date:Date = new Date();
          textArea1.text = date.hours.toString()+
             ":"+date.minutes.toString()+
             ":"+date.seconds.toString()+
             ":"+date.milliseconds.toString();
       }   

       protected function start_clickHandler(event:MouseEvent):void
       {
           myTimer = new Timer(1000);
           myTimer.addEventListener("timer", timerHandler);
           myTimer.start();
       }

       protected function stop_clickHandler(event:MouseEvent):void
       {
           myTimer.stop(); 
           myTimer.removeEventListener("timer", timerHandler);
       }
  ]]>
 </fx:Script>

 <s:TextArea id="textArea1" x="15" y="70" width="270" height="20"/>
 <s:Button x="15" y="28" label="Start" click="start_clickHandler(event)"/>
 <s:Button x="103" y="28" label="Stop" click="stop_clickHandler(event)"/>
</s:Application>