Friday, May 23, 2008

ESRI Holistic Lab: Flex API Day 2

Day two for me consisted mainly of trying to get an extent QueryTask to work in order to do feature selections. I had already created a map service on my machine which exposed a set of utility data. My first task was to create a graphic to allow users to click and drag to create an extent for their selection. This was somewhat less straight forward than in the old ArcWebServices version of the Flex API as there is currently no easy way to draw an interactive extent on the map with no mouse handler interface and toolkits not yet implemented. One of the Flex API team members gave me a sample which got me jumpstarted however. In the end it was a case of simply hooking the mouse down, mouse move, and mouse up events. The tricky part was getting the extent rectangle to draw the way I wanted. I never really got it to look the way I wanted, but I did get it to work. The really nice thing about this is that using the new REST api available in 9.3 you can query on a layer with no custom web services. The query capability of the REST api is nicely wrapped up within the QueryTask object. I’ll not go into too many details about it because I don’t want to push the NDA I had to sign too far but the Task interface is going to make a lot of people happy, not to mention making their jobs easier when creating flex applications.

We also sat together as a group for a couple of hours in the morning and afternoon and talked about basic Flex programming dos and don’ts. Many of the following ideas come from the Cairngorm flex framework http://labs.adobe.com/wiki/index.php/Cairngorm

Code-behind

We started out by going over the basic GUI coding paradigm of code-behind and how it works in the Flex world. The best way to do this is to create your own Actionscript class, MyApp for instance, which has Application as a super class. You then create your base application mxml and have it subclass your MyApp Actionscript class. At this point you can put all of the code you need to run your application within its own actionscript class and keep it completely separated from the mxml gui tags. In order to access your gui items from your MyApp class you must declare a public variable within your class with the same name and type as the items within the mxml. So if you have a in mxml then you would need a public myLabel:Label declared within your MyApp to be able to access it.

The names that you give your objects now become very important because you will be coding the logic in a separate file from where the GUI is created. If you name your objects and event handlers poorly you will have trouble keeping up with what functions and items do what. Therefore it is good to not only give your objects meaningful names but to also follow a standard when naming your event handlers. Using the convention of objected_eventNameHandler() is the standard way of naming your event handlers and does a good job of concisely informing you on what it is (an event handler), what type of event it handles and for what object it does the handling.

Making use of Singletons

Cairngorm recommends creating a bindable singleton class which holds on to all of your application level information and allows any class to manipulate that class level data and always be sure that it is the correct version of the data. Making the class bindable also allows other classes to bind to these application level variables and be automatically updated when those values change. The Flex API team called this class the Model. We used a singleton class in our original Network Express prototype which definitely made life much easier but the one we were shown had a couple of advantages over the one we used previously. Chief among these was the ability to make sure that only one instance of the Model is ever created, and the ability to be certain there is only ever one instance of any given application level object.

The Flex Object Lifecycle

All objects which are created in the Flex world go through the same cycle when they are created. There are several events and functions which fire off that can be overloaded to allow you as the programmer to perform specific functions even before the CreationComplete event has fired.

·

  • New (Label) – the first step is the object instantiation is started.
  • PreInitialize – an event dispatched before any actual initialization takes place.
  • Setter – calls all Set functions
  • Initialize – another event dispatched to alert of actual initialization
  • CommitProperty – a function. Overriding this function will allow you to make changes to the object atomically, preventing flashes and other artifacts from occurring as properties are set.
  • CreateChildren – function which starts the Lifecycle on all children objects. This is another function which can be overridden.
  • Measure – Sets all of the width, height, etc.
  • UpdateDisplayList – function that adds the new object to the display list atomically.
  • CreationComplete – the final event which signals that the object is complete. This is called only once.


Simply knowing about this lifecycle opens a lot of possibilities, especially with the functions which can be overridden.

Tips:

1. Make sure to listen to the Load event on map objects as the CreationComplete event will fire well before any layers have actually been loaded. Trying to manipulate the map before the Load event will only cause you heartache, and errors. Each individual map layer will also fire a Load event.

2. Always call super on all overloaded functions. Failing to do so will keep the normal behavior from occurring.

For more information on the Flex lifecycle check out this document: http://livedocs.adobe.com/flex/2/docs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000492.html

Events

Let’s say you have an application with a VBox that contains a button. The display tree would look like: Application --> VBox --> Button. If you were too hook into the click event on this button then I’m sure you can guess that your function will be informed when the button is clicked. What you might not know however is that Every item in the display list starting at the top will receive a click event as well. This means that if you were to hook the click event on the VBox or the Application you would catch an event each time the button was clicked as well. So how does your function know if the event it catches was meant for it? The event object has target and currentTarget properties. The target property contains the id of the actual target of the event and the currentTarget property contains the id of the item in the display list currently receiving the event.

Events also have a phase. There are two event phases: capture and bubble. The capture phase occurs as the event is making its way down the display list looking for the target. If you need to cancel an event for some reason you would want to handle it during the capture phase. The bubble phase occurs on the way back up to the top of the display list. When a handler is added it will fire by default on the bubble phase. There is also a bubbles property on an event which is set to true by default.

Delegates and Unit Testing

During the afternoon of day 2 we sat down together and did a quick example application using Delegates which we then performed unit testing upon. Delegates take the idea of code-behind a step further. Once you have your mxml application and the code for it separated, you then perform all of the actual logic of your program via Commands. These commands are called by events in your code-behind which then in turn call their own Delegate classes which perform all of the actual work. The Commands are then in charge of making changes to application level data within your Model. Delegate classes are completely independent of the rest of your program, not caring how they are used as long as they receive their input in the correct form. The Delegates for your application can even be removed to separate swc libraries without causing any issues. This allows teams to break up tasks fairly easily and logically. One person can be in charge of creating the GUI for the application, another in charge of the code-behind application and commands, and yet another person or group can be in charge of creating the Delegates to actually perform the logic of the application.

Unit testing can be performed on Delegate classes very easily because they have well defined inputs and outputs. As long as a Delegate receives input in the correct format it doesn’t matter where it comes from. The unit testing framework we used was Flex Unit http://code.google.com/p/as3flexunitlib/ which is a free download and a very slick addition to your Flex environment which I highly recommend and plan to use myself.

Tips:

When your mxml application is compiled by the flex compiler it goes through several steps. First it is parsed into MXMLC and then it is translated into an actual actionscript (as3) file before being compiled into a swf. Now I know what you’re thinking, wouldn’t it be nice to see how flex natively converts all of those mxml tags into neat concise code? Well it turns out that you can. There is a compiler setting which allows you to tell the compiler to leave all of those as3 files behind instead of deleting them once it is finished, allowing you to learn all types of tips and tricks by seeing how the compiler creates all of that code.

No comments: