| By Yakov Fain | Article Rating: |
|
| February 14, 2008 02:45 AM EST | Reads: |
16,058 |
Flex is all about event-driven development. Create loosely coupled objects and let them send events to each other. You can read about this in the following blog.
In a nutshell, you can create new events for every occasion. If an event doesn't need to carry any additional data, just extend flash.events.Event and define the meta-tag to help Flex Builder list this event in its type-ahead prompts and dispatch it when appropriate. If your new event needs to carry some data, create an ActionScript class, define a variable in your subclass to store your data, and override the method clone().
If we take a mid-size Website with 10 views, where each view has two components that can send/receive two events, you can quickly reach 40 or more custom Event-based classes that look pretty much the same. To ensure that the situation does not get out of control, some of the Flex frameworks force you to register each event upfront in a central location.
We say, “No need to do it. You can get away with one event.” The sample application below has only one defined event class that can fit multiple purposes without the need to introduce tight coupling between your application components.
To illustrate the concept, I’ve created a simple application that looks as follows:

This application consists of two modules (GreenModule and RedModule) that are loaded in the same area of the main application with the click of the appropriate Load button. It also has one universal event class called ExEvent. If you click on the Send buttons, an instance of this event is created and there you can put an instance of Object, a DTO, a couple of string variables, nothing, or anything else you like. In this example I’m using a DTO class called GirlfriedDTO.as. There is no mapping between the event you send and the modules. For example, if you send a Green event to the Red module, nothing happens since the Red module is not listening to the Green event.
I’ve been using modules in this application, not because I endorse them, but because they give me a chance to quickly illustrate a concept of run-time loading and loose coupling between the objects and events. Victor Rasputnis, my colleague at Farata Systems, has been experimenting with modules and next month will publish an article that describes his findings.
A completed application and its source code is deployed at this URL. Its Flex Builder’s project has a folder module that contains two modules: red and green. The red one is listening for the arrival of the girlfriend’s first and last name, packaged in our single event class as two separate strings:
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
width="100%" height="100%" creationComplete="onCreationComplete(event)">
<mx:TextArea id="display" backgroundColor="#FF4949" width="100%" height="100%" fontSize="28"/>
<mx:Script>
<![CDATA[
private function onCreationComplete(evt:Event):void{
this.addEventListener("RedGirlfriend", onRedGirlfriend);
}
private function onRedGirlfriend(evt:ExEvent):void{
display.text="My girlfriend is "+ evt.fName+ " " + evt.lName ;
}
]]>
</mx:Script>
</mx:Module>
The green module expects the girlfriend’s name in a form of GirlfriendDTO:
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%" height="100%"
creationComplete="onCreationComplete(event)">
<mx:TextArea id="display" backgroundColor="#9CE29C" width="100%" height="100%" color="#070707" fontSize="28"/>
<mx:Script>
<![CDATA[
import dto.GirlfriendDTO;
private function onCreationComplete(evt:Event):void{
this.addEventListener("GreenGirlfriend", onGreenGirlfriend);
}
private function onGreenGirlfriend(evt:ExEvent):void{
var myGirlfriend:GirlfriendDTO=evt["girlfriend"];
display.text="My girlfriend is "+ myGirlfriend.fName+ " " +
myGirlfriend.lName ;
}
]]>
</mx:Script>
</mx:Module>
The GirlfriendDTO is located in the folder dto and is pretty straightforward too:
package dto
/**
* This is a sample data transfer object (a.k.a. value object)
*/
{
public class GirlfriendDTO
{
public var fName:String; // First name
public var lName:String; // Last name
}
}
Now let’s talk about our single but universal event class. It’s based on the DynamicEvent class, which allows you to add any properties to the event object on the fly. Surprisingly, Flex documentation discourages you from using this class. Here’s what it states:
This subclass of Event is dynamic, meaning that you can set arbitrary event properties on its instances at runtime. By contrast, Event and its other subclasses are non-dynamic, meaning that you can only set properties that are declared in those classes. When prototyping an application, using a DynamicEvent can be easier because you don't have to write an Event subclass to declare the properties in advance. However, you should eventually eliminate your DynamicEvents and write Event subclasses because these are faster and safer. A DynamicEvent is so flexible that the compiler can't help you catch your error when you set the wrong property or assign it a value of an incorrect type.
Let me respectfully disagree with this recommendation and suggest you use the dynamic nature of this event, not only for prototyping, but also for development and deployment of your applications. When GUI components send event sto each other, the difference in the processing of your dynamic versus static event instance is negligible. It’s not clear how much safer the static event is. I don't think so.
When you design an event-based interaction between components of your applications, both the sending and receiving parties must know in which format the data is being delivered by an event. And we utilize this knowledge even in case of the dynamic events. We can use either a well-defined GirlfriendDTO:
var myDTO:GirlfriendDTO=new GirlfriendDTO();
myDTO.fName="Mary";
myDTO.lName="Poppins";
var greenEvent:ExEvent=new ExEvent("GreenGirlfriend");
greenEvent.girlfriend=myDTO;
someObject.dispatchEvent(greenEvent);
or just add two string variables:
var redEvent:ExEvent=new ExEvent("RedGirlfriend");
redEvent.fName="Mary";
redEvent.lName="Poppins";
someObject.dispatchEvent(redEvent);
In this sample I use an ExEvent, which is a subclass of the DynamicEvent – it has just a minor enhancement that eliminates manual programming of the property Event.preventDefault:
package
{
import mx.events.DynamicEvent;
{
private var m_preventDefault:Boolean;
public function ExEvent(type:String, bubbles:Boolean = false,
cancelable:Boolean = false) {
super(type, bubbles, cancelable);
m_preventDefault = false;
}
// It's an enhancement: DynamicEvent class does not
// automatically process preventDefault in cloned events
public override function preventDefault():void {
super.preventDefault();
m_preventDefault = true;
}
public override function isDefaultPrevented():Boolean {
return m_preventDefault;
}
}
}
Now the code of the test application loads modules, and then the user can send any event to whichever module is loaded at the moment. Of course, if the currently loaded module does not have a listener for the event you’re sending, tough luck. Do not expect miracles – nothing will happen. But the good news is that it won’t break the application either:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" viewSourceURL="srcview/index.html">
<mx:HBox>
<mx:Button label="Load the Green Module" click="loadMyModule('modules/GreenModule.swf')"/>
<mx:Button label="Load the Red module" click="loadMyModule('modules/RedModule.swf')"/>
<mx:Button label="Send Green Event with Object" click="sendGreen()"/>
<mx:Button label="Send Red Event Event with two strings" click="sendRed()"/>
</mx:HBox>
<mx:Panel width="100%" height="100%" title="A module placeholder" layout="absolute">
<mx:ModuleLoader id="theModulePlaceholder" width="100%" height="100%"/>
</mx:Panel>
<mx:Script>
<![CDATA[
import dto.GirlfriendDTO;
//Load the module specified in the moduleURL
private function loadMyModule(moduleURL:String):void{
theModulePlaceholder.url=moduleURL;
theModulePlaceholder.loadModule();
}
// Sending generic ExEvent adding an object that contains
// the name of the girlfriend
private function sendGreen():void{
// Strongly typed DTO - better performance and readability,
// but its structure has to be known for both parties -
// the main application and the module
var myDTO:GirlfriendDTO=new GirlfriendDTO();
myDTO.fName="Mary";
myDTO.lName="Poppins";
if (theModulePlaceholder.child !=null){
var greenEvent:ExEvent=new
ExEvent("GreenGirlfriend");
greenEvent.girlfriend=myDTO;
theModulePlaceholder.child.dispatchEvent(greenEvent);
}
}
// Sending a generic ExEvent that holds the name of the girlfriend
// as two separate variables
private function sendRed():void{
var redEvent:ExEvent=new ExEvent("RedGirlfriend");
redEvent.fName="Angelina";
redEvent.lName="YouKnowWho";
if (theModulePlaceholder.child !=null){
theModulePlaceholder.child.dispatchEvent(redEvent);
}
}
]]>
</mx:Script>
</mx:Application>
The function sendGreen() sends an instance of our ExEvent event with DTO, while the sendRed() just adds two properties, fName and lName, to the instance of the ExEvent.
Instead of using a well-defined DTO, I could’ve used a weakly typed data transfer object:
var myDTO:Object={fname:"Mary",lname:"Poppins"};
But this would result in poor readability of the code and a bit slower performance. On the positive side, there would be no need to explicitly define and share the class structure of the dto between the app and the module. I’d do something like this during the prototyping stage, but not in real code.
Let’s recap. What did we gain? No need to create lots of tedious coding, defining dozens of similar event classes. What did we lose? Since we did not use the metatag Event declaring the names of the events, those never declared event classes, Flex Builder won’t be able to help us with the name of the event in its type-ahead help. No biggie.
In the unlikely case if there is a view in your application that can’t afford to lose a couple of milliseconds caused by using a dynamic event, use static but in that view only. But with a single dynamic event, the code base of your project will become smaller and more readable.
Published February 14, 2008 Reads 16,058
Copyright © 2008 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Yakov Fain
Yakov Fain is a Managing Director of Farata Systems, consulting, training and product company. He has authored several Java books, dozens of technical articles. SYS-CON Books released his latest co-authored book , Rich Internet Applications with Adobe Flex and Java: Secrets of the Masters in Spring 2007. Sun Microsystems has nominated and awarded Yakov with the title Java Champion. He leads the Princeton Java Users Group. He is an Adobe Certified Flex Instructor. Currently Yakov works on the book for O'Reilly "Enterprise Application Development with Flex". He twits at twitter.com/yfain.
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Adobe’s Aiming ColdFusion at Multiple Clouds
- Cloud Computing Journal: Adobe to Deliver ColdFusion in the Cloud
- Adobe Unveils LiveCycle Enterprise Suite 2 for Deployment in the Cloud
- Adobe Flex Developer Earns $100K in New York City
- Adobe May Cooperate with Apple to Transplant Flash Player to iPhone
- Ph.D. in Twitter Anyone?
- Eolas Sues the Internet
- Adobe LiveCycle Enterprise Suite 2 for Cloud Computing
- Adobe Betas Target RIAs and Cloud Computing
- Special Report on the Emerging Cloud Computing Trend
- Adobe Cans Another 9% of its Workforce
- My Thoughts on Ulitzer
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Ulitzer Live! New Media Conference & Expo
- Adobe’s Aiming ColdFusion at Multiple Clouds
- Eval JavaScript in a Global Context
- Fig Leaf Software to Exhibit at Government IT Conference & Expo
- Cloud Executives Feature on Cloud Computing Expo Power Panel
- Software Flexibility in the Cloud - Part 4 of 5
- Cloud Computing Journal: Adobe to Deliver ColdFusion in the Cloud
- Is Microsoft as Free as Open Source?
- Adobe Reader Sued
- Adobe Unveils LiveCycle Enterprise Suite 2 for Deployment in the Cloud
- Where Are RIA Technologies Headed in 2008?
- Cover Story: How to Increase the Frame Rates of Your Flash Movies
- AJAX World RIA Conference & Expo Kicks Off in New York City
- Your First Adobe Flex Application with a ColdFusion Backend
- Adobe Flex 2: Advanced DataGrid
- i-Technology Blog: Death-Knell For "Rich Media? Hardly!
- Adobe/Macromedia - Microsoft, Look Out!
- How To Create a Photo Slide Show ...
- Adobe Flex Interface Customization - Themes, Styles, Skins
- Personal Branding Checklist
- Has the Technology Bounceback Begun?
- "Real-World Flex" by Adobe's Christophe Coenraets



































