If you are relying on the built in Flex binding mechanism, you may have run into this issue: The Binding won’t update its listeners if the value you are setting the property to is the same as the previous value. Put another way:
var a:Number = 10;
trace(a); //firing the getter which outputs 10.
a = 10; //firing the setter, bindings will not update listeners.
Do not rely on Flex to fire the propertyChangeEvent w/ respect to the related getter/setter by using the default [Bindable] metatag. Instead modify your class with these steps:
- Instead of
[Bindable], use[Bindable (event="myCustomEventName")]on your getter. - Make sure the related setter dispatches the event like so:
dispatchEvent(new Event("myCustomEventName")); - Also making sure to add
[Event (name="myCustomEventName", type="flash.events.Event")]for any external listeners. - Implement custom logic on the listeners in questions so that they can be updated via the event rather than the binding.*
How this might assist you? Well rather than relying on having to circumvent the binding not firing when setting the property to the same value, you could have additional listeners for that custom event since it is fired regardless of the previous set value.
*Although I do use this method on all of my getters/setters, I would not necessarily implement the external logic on all of the bound listeners. I would only do so in cases where the property needs to be updated regardless of whether or not the new value is the same as its previously set value.
If you have ever peered into one of the mx classes, you will probably have noticed the ubiquitous mx_internal namespace being used. For those of you not familiar with the usage of namespace, it is basically a system of allowing classes to peer into other classes for needed code. The most common namespaces are:
publicprotectedinternalprivate
So the mx_internal namespace is a kind of extension of the internal namespace, but rather than being limited to seeing other internal properties and methods of just a particular package, it is able to see code through out the entire mx framework. For example, the Panel, which resides at mx.containers has mx_internal function getTitleBar(), which makes the protected var titleBar visible to any other component within the mx framework.
So what can this do for you as a component developer. Well, you can easily tap into these methods and properties yourself. All you need to do is add two lines of code to your class.
include mx.core.mx_internal;
and
use namespace mx_internal;
Now any property or method with the namespace mx_internal is accessible to your class. But be forewarned, there are two issues with doing this.
- Adobe has written in their code the following caution:
This namespace is used for undocumented APIs — usually implementation details — which can’t be private because they need to visible to other classes. APIs in this namespace are completely unsupported and are likely to change in future versions of Flex.
This means you might be in for a surprise the next Flex SDK update you do.
- You don’t get code hinting in your IDE since technically speaking you are not even supposed to be implementing these APIs.
Anyway…hope this might provide some solutions to any component developers out there that are stuck with a particular extension problem.
[EDIT 2007.05.14] – A buddy of mine found a cool but not-so-OOP way of accessing a component instance’s mx_internal properties. I would be very careful with getting into the habit of this. Check it out.
NOTE: This post will no longer be maintained. For the most up-to-date version of this post go to the dedicated page.
DICTIONARIES/REFERENCE:
TUTORIALS:
FORUMS:
- Kirupa forums – (one of the nicest communities out there)
- Actionscript.org forums
- Flexcoders
- FlexComponents
PROJECTS/SOURCE CODE:
OTHER RESOURCES:
- Flex Performance Tips (added 05/01/07)
- Flex 2 Style Explorer
- Flex skinning
- Flex Display Architecture
- Flex component development links
- Flex component development guide.pdf
- Metadata tags in AS3.0
If you can think of some I haven’t, please post a comment and I might add them here.
Being the ego-centric human that I am, I often check out my blog stats. Yes, I am guilty of using my blog as a means of shameless self promotion. Who out there writing a blog isn’t in some way?
Anyhow I am going through, checking in on some of the incoming links and found this nay-sayer. Basically our friend here is saying that the Flex framework is a failure because it requires some…
- …insight into the flex framework,
- some sense of exploration,
- and a developer who likes a challenge.
I am no flex evangelist (yet) but I think the benefits (see list below) that Flex and Flash offer by-far outweigh the concerns of this ass-clown. I am curious as to what he proposes as a more suitable framework over the Flex/Flash, which currently has this over its competitors:
- near ubiquity in mature markets. Check out some of the flash player adoption stats here.
- cross browser compatibility
- cross platform compatibility
- better player updates that are nearly transparent to the user
- far better accessibility hookups than HTML or AJAX
So I think these benefits are pretty hard to argue and have been established for quite some time. This doesn’t even include developer-targeted benefits. So Mr. NotBoss, as a child did you expect to get your Legos/K’nex/Lincoln Logs fully assembled for you?
Anyway, the defense rests. No further questions Your Honor.
Awhile back I had developed (as many of you may have already) a Panel subclass. Basically I needed a way to add buttons to the titleBar area much like the mx:TitleWindow has the close button. The end result being something very similar to a Window’s Explorer window (not IE). Well if you have tried this, then you know it is not as simple as just saying titleBar.addChild().
A developer’s initial approach may be to override updateDisplayList and createChildren to insert child components inside the titleBar. This was my initial take on it. But this is flawed in that you are…
- …unnecessarily overriding methods not generally associated with this area of the Panel. UpdateDisplayList in a nutshell is used to update child components. In terms of mx:Panel, generally child components are what a developer sticks inside the content area. CreateChildren is again something generally associated with child components. Basically these methods are the wrong place to insert items in the titleBar area.
- The other flaw in this is that it inefficiently/unnecessarily renders your new titleBr assets. For instance, you want to add 3 buttons to the Panel’s content area. Now let’s assume that the Panel will remain a fixed width and height. So not including calls to these methods during pre-child attachment phases, we are calling these methods 3 times each per button.
I should probably start prefacing my posts with a disclaimer that they are simply guess-timations on the flex framework as I haven’t done any true performance testing and/or benchmarking on my findings. But what testing I have done has yielded positive results. So what I am really trying to say is, correct me if I am wrong.
After doing some peeking into how Panel (not TitleWindow) does the close button logic, I found that it isn’t really tapping the aforementioned methods. The only time it was really calling the createChildren method was to attach the titleBar to its rawChildren and the subsequent children of the titleBar. No layout, sizing, etc was really being handled in this method. More about this later….
Firstly I wanted to be able to make my Panel subclass scalable in that I could have one guy with 3 buttons in the titleBar and then another with one. Also I wanted to be able to attach functionality on the instance’s buttons rather than have a class with hardcoded click listeners. So I just made a simple public method addTitleBarButton (value:Button = null):Button. This method basically takes/creates a button, adds it to an array, then adds it to the titleBar. Lastly it returns the button in case you need to do more to it later on. Just doing this though will not display the items added. You need to resize and reposition them as well. Onto a bit about rawChildren.
Panel’s titleBar is considered a rawChild. So it is not really counted in the displayList (at least directly). This is also true of alot of the skins associated with the container’s borders. When Panel needs to update its borders and titleBar, it does so via LayoutChrome. So this would be an ideal place to add some logic to any new titleBar assets. Now you can get those newly added buttons from that array I mentioned earlier. Then by cycling through the array and getting some x, y, width and height info we can see the new title buttons inside the titlebar area. All without even touching the createChildren or updateDisplayList.
Remember when you were told to end your sentences with punctuation in grammar school? If you are coming from and ActionScript background, you may have gotten lazy about ending your sentences with the AS equivalent of the period:”;”.
Normally the compiler doesn’t gripe about it. Much like your dear ol’ teacher, it grades your code on content and syntax rather than punctuation. However in the case of the metatags being inside the body of the script or class, it doesn’t like it. Here’s an example:
[Bindable]
public var t:Boolean = true
[Bindable] //will throw the error here
public var s:Boolean = false;
To fix that you simple need to make sure the ; was on the sentence above like so:
[Bindable]
public var t:Boolean = true;
[Bindable] //you get an A+ Timmy
public var s:Boolean = false;
I haven’t done any testing on if this is only applicable for mxml based components simply because I am lazy. Maybe later.
UPDATE (5 minutes later):
So I am feeling a bit inspired. I ran the same test on an ActionScript class and lo and behold I get “An internal build error has occurred. Please check the Error log.” Now I am feeling lazy again (really I forgot where to find the log file) and so i will break again. Teacher???? what gives???
This may be common knowledge or may not but I figured I would sound off on the topic. During some performance optimization a coworker came across some issues with container type classes in Flex, specifically nested containers. We had some less-than-ideal approaches regarding the layout of some of our custom components within our application.
For instance, we have a class that was in the general sense, a modified image type class with some mouse event handlers. Rather than extending the image class using the OOP’s “is a” mentality, it was developed with the “has a(an)” approach. This meant that the class base was something like a container with an image instance contained within. Then the mouse event handlers were assigned via the MXML events on the image item. I’d attribute this development approach to the fact that the person was probably crunched for time, frequent refactoring due to the Agile approach we have adopted, and/or they were not familiar in programming event handlers for a class’s own events (i.e. tapping into the mouse events on a Image subclass and assigning internal handlers).
Now I am not saying there is a huge performance difference in the “has a” approach. On a one-to-one comparison you’d probably be hard pressed to see even a significant difference. But on larger applications where there are dozens, if not hundreds of container type classes being used, it could mean the difference between fast rendering and very sluggish rendering. In our case, my coworker refactored a small section of the application and saw improvements that resulted in seconds, not milliseconds.
The reason for the performance hit is this (or at least my take on it): Every time updating occurs on dimensions, positions, indexes, children, etc., there are a whole slew of methods that fire off. This is compounded if the container in question has children because normally they too call those methods for themselves. So now we are taking a slight performance hit and exponentially increasing it. Of course all these things are taking place very quickly but still, performance is taking a hit.
So the suggestions for improvement are:
- reevaluate the “is a” vs. “has a(an)” relationship developing classes.
- if a container is being used solely for ease of internal development such as event tie-ins, consider another approach.
- When making updates to things such as dimensions, positions, indexes, children, etc., consider ways to aggregate those updates into fewer calls.
- Check out ways to make use of direct calls to
invalidateDisplayList(), invalidateProperties(), andinvalidateSize(). Normally these are called indirectly via setter functions on their respective variables.
I am sure there are plenty of other means to improving performance as well.
Now I want to get into my proposed approach. If you are just now joining us and didn’t catch part 1, you can catch up here.
Keep in mind this is still in the infant stages and I am currently developing and rethinking how this works. I certainly welcome ideas, criticism, and recommendations on my approach. So please hammer away. Onto the code….
The first step is to allow our commands a means of firing events when they do their result and fault logic. So we need to extend the EventDispatcher class. I created a base class called CommandBase that extends the EventDispatcher and implements ICommand and IResponder. So we are still maintaining the whole Command architecture in respect to Cairngorm 2.1. You could easily do this using the deprecated Cairmgorm Responder interface as well. So now every command we create just needs to extend CommandBase and override the execute, result and fault methods. But in doing so we need to make sure to call the super.execute(), super.result() and super.fault() methods as well or at least dispatch those events when overriding. Here is some sample code:
[Event (name='execute', type='flash.events.Event')]
[Event (name='result', type='flash.events.Event')]
[Event (name='fault', type='flash.events.Event')]
public class CommandBase extends EventDispatcher implements ICommand, IResponder {
public function execute (event:CairngormEvent):void {
dispatchEvent(new Event('execute'));
}
public function result (data:Object):void {
dispatchEvent(new Event('result'));
}
public function fault (info:Object):void {
dispatchEvent(new Event('fault'));
}
}
Really simple stuff and in fact it looks exactly like your regular ol’ Cairngorm Commands you have been using for quite awhile. Next we need to setup a Sequence type Command. I decided to go with SequenceCommandBase which extends…yep, you guessed it CommandBase. Why? Well, code reusage for one and also I think there may be some crazy times when you want to nest these guys. Now SequenceCommandBase has quite a bit of added stuff in order to work correctly. We have a command queue, a current index, and a command log that we can use for tracing and tracking stuff. We also have added a few more methods which I will go into detail. When I started thinking about how to decouple these sequenced commands, I came up with a few thoughts on what was needed to assist this concept:
- a reference to the command class
- events for the commands
- contingency for a failed command within the sequence
Well the first point is handled pretty much the same way Cairngorm’s FrontController handles creating new events. You pass a class reference and it create a new instance of that particular class. Like in a mx.effect.Sequence we need a means of attaching child commands. I chose to use addCommand rather than addChild. I am passing a few parameters as well and assigning event handlers to the command’s result and fault events. The tricky part is how to handle events for the commands in question during the execution phase.
In a normal application of the command pattern, we just dispatch our CairngormEvent via the CairngormEventDispatcher. So events are created and almost immediately used. In our case, we are predefining the events. Normally this is not an issue. We can just create them when we add the commands and then when the commands are executed, we pass the predefined events in with it. But what happens if there are what I call data modification dependencies? Meaning what if there is a dependency on data that may be altered by a previous command’s result or failure. For example, commandTwo needs a value in the Model which currently is set to “”. And we need commandOne’s result to set that value in the Model. If we are predefining these events based on those values then we will get the original value and not the previous command’s result’s assigned value. Right now, I have a solution, but not a very elegant solution. For now I am passing an event modifier function as another parameter when we add child. These modifiers will most likely be defined in the subclasses of SequenceCommandBase.
Next we need to execute each command. I called it executeCurrentCommand. Pretty original huh? Basically it does a few things. It does what it says namely, but before doing so it also does the following:
- checks to see if we have an event,
- if not creates a generic CairngormEvent,
- sees if there is any needed modification to the non-generic event if we passed in during addCommand,
- creates an instance of the current command class (remember which will be a subclass of CommandBase).
- executes the current command and passes the current event as the parameter.
So you might be thinking, isn’t that what the FrontController does? Yes. But unfortunately since the FrontController subclasses create new instances of the needed commands on the fly, we can’t really tap into that functionality. So right now the SequenceCommandBase is also subbing as a mini-FrontController.
The next set of methods are really event handlers for the current command’s result/fault events. But they do handle the contingency logic for what happens if something fails. But first I should explain the command queue a bit further. It not only stores the commands, it also stores references to their respective events, event mod functions, and the boolean values as to handle what to do on failures. So when the current command fails or succeeds then the respective event chimes in and says, “well if he succeeded then go on to the next command, but if he failed then we need to follow his contingency booleans and execute the logic to see if we proceed or blow chunks.”
So I guess this would be a really good time to start pasting more code. Okay here is a sample of the addCommand method:
public function addCommand (commandClass:Class,
event:CairngormEvent = null,
eventModificationLogic:Function = null,
continueOnFaultFail:Boolean = false,
jumpOnFaultFail:Boolean = false,
jumpIndex:int = 0):void {//is there a more elegant way of handling this?
var command:CommandBase = new commandClass();
command.addEventListener(‘result’, onResult_currentCommandHandler);
command.addEventListener(‘fault’, onFault_currentCommandHandler);_commandQueue.push([command, event, eventModificationLogic, continueOnFaultFail, jumpOnFaultFail, jumpIndex]);
}
Here is a glimpse of what is currently the logic behind the execution:
protected function executeCurrentCommand ():void {
//checking to see if we need to update the event before executing the currentCommand
if (_commandQueue[_currentIndex] [SEQ_EVENT_MOD_INDEX]){
var func:Function = _commandQueue[_currentIndex] [SEQ_EVENT_MOD_INDEX] as Function;
}var currentCommand:CommandBase = _commandQueue[_currentIndex] [SEQ_COMMAND_INDEX] as CommandBase;
var commandEvt:CairngormEvent;if (_commandQueue[_currentIndex] [SEQ_EVENT_INDEX] == null){
commandEvt = generateGenericEvent();
} else {
commandEvt = _commandQueue[_currentIndex] [SEQ_EVENT_INDEX] as CairngormEvent;
}currentCommand.execute(commandEvt);
}
And finally here is some quick code for the handlers :
protected function onResult_currentCommandHandler (evt:Event):void {
updateLog(‘RESULT’);
_currentIndex++;
executeCurrentCommand();
}protected function onFault_currentCommandHandler (evt:Event):void {
var allowPassThru:Boolean = _commandQueue[_currentIndex] [SEQ_ALLOW_CONTINUE_INDEX] as Boolean;
var allowJumpTo:Boolean = _commandQueue[_currentIndex] [SEQ_ALLOW_JUMP_INDEX] as Boolean;
var jumpTo:int = _commandQueue[_currentIndex] [SEQ_JUMP_INDEX] as int;if (allowPassThru){
if (allowJumpTo){
updateLog(‘FAULT JUMP’);
_currentIndex = jumpTo;
} else {
updateLog(‘FAULT PASS’);
_currentIndex++;
}executeCurrentCommand();
} else {
updateLog(‘FAULT TERMINATE’);
fault(_commandLog);
}
}
I apologize for the fact I don’t have a REAL blog where I can format the code. Maybe here shortly I will, but for now I am stuck with the free online blog @ wordpress.
Anywho. Let me know some of your thoughts. Again, keep in mind that this is just a proof-of-concept in progress and will evolve.
Thanks ,
Jwopitz
With an ever-growing code base on our ever-growing project, I have been doing quite a bit of thinking regarding the Cairngorm SequenceCommand. It seems that every time we add a new feature, we have to add at least one new command, that is just a slight variation on the same thing. This is especially true in our initialization of our application. It could be even more true if you were using a modular type approach to building your applications.
During the initialization of our application, a chain of SequenceCommands fire off to get their needed data. There are also times that this same information needs to be retrieved out-of-sequence or retrieved solely on its own. So in a traditional approach, you would have a regular Cairngorm Command subclass when you need this information out-of-sequence, and then an almost duplicate Cairngorm SequenceCommand for those times previously mentioned. So essentially you are duplicating the needed code to achieve the same results. And the reason this is, is because the logic to perform the ‘guts’ of the SequenceCommand has some dependencies on the next command to be called. This then can have an effect not only the command in question but also the possible command preceding it and/or the next command as well.
I don’t like this for a few reasons:
- unnecessary code duplication.
- code dependencies at the logic level of the commands (increased coupling?).
- ripple effects for related commands.
So I started to think about how to make this process more efficient. How could I achieve code re-usage and still maintain the ability to ’sequence’ commands together. I have been looking at how the mx.effects classes work. You can have a Move instance do something once like move a box from ptA to ptB. You can also have several other effects do their tasks, and then turn around and use your Move instance again. You can even chain Move along with those other effect to fire off in sequence with out modifying the original instances’ properties. So why can’t the same be applied to how we chain commands together? I think it can with very little effort. We’ll talk about the details in part 2.
If you have ever tried to do component development, you know it can sometimes be a pain because certain methods in the parent class are marked private and are inaccessible to your class. Take for instance the comboBox. When making my custom component (which subclasses comboBox), I wanted to customize some event handling for the listBase. The getDropdown function is where you would (if you could), override the native event handling and plug in your own functionality. But I can’t. Why? Its marked private. “Couldn’t you override the assigned event handlers for the listBase?” Hmmm. Sounds like a plan. Nope. Let’s take a look to see why.
- dropdown_changeHandler
- dropdown_scrollHandler
- dropdown_itemRollOverHandler
- dropdown_itemRollOutHandler
- dropdown_mouseDownOutsideHandler
- dropdown_mouseWheelOutsideHandler
- dropdown_itemClickHandler
All these guys are marked private instead of protected. Certainly alot of the ‘heavy lifting’ has been for most developers in that they will probably never need to modify these methods. But for a component developer this can pose major problems. In my particular case I wanted to override the dropdown_itemClickHandler in order to intercept and do something to the event getting dispatched. “Couldn’t you just add an eventListener in your subclass and tie in your functionality there?“. Yes, I could but then I would still have the super’s event handler logic taking place, which I don’t want.
So what are the solutions here? Well you have two options at the moment.
- live with it and find another solution.
- copy the super code to a project directory and change the needed code to protected.
I did the latter. It doesn’t sit well with me but I will live. But there is one more thing I did. I suggest if you ever are in the same situation that you save this link. Let Adobe know about it and gripe about it until it gets changed in the next update.
http://www.adobe.com/cfusion/mmform/index.cfm?name=wishform
I can understand in the rush to get something out the door that old AS2 programming habits creeped in. But this should be remedied on the next update.
