Flex :: commitProperties(), a components state queue
Hi,
I am starting a series on the flex framework from a component developers point of view ( after much experience). Expect useful articles from a professional and experienced component developer.
Some of you may know what I am talking about others might learn something.
I see some things in a different light now that I have been developing components for a year and a half.
Flex offers a unique way of validating your component when performance is a necessity.
- component property state
- component measurement
- component layout
AKA;
commitProperties()[This issue]measure()updateDisplayList()
Properties
Properties in your component hold it's current state. When we talk about state in this respect we are referring to changes made from it's default base state. The default state is what the component's class defines as it's starting point.
In the code above, we set the private variable _moveEnabled to false. We have now set the default move enabled state of the component.
Updating Properties
There is now a way to set the base state but, as you can see the access is private, only for this classes eyes. We now need to create a point at which a developer can change the component's move enabled state.
Enter public properties;
protected var moveEnabledChanged:Boolean = false;
/**
* Enables the movement of the component.
*/
public function get moveEnabled():Boolean
{
return _moveEnabled;
}
/**
* @private
*/
public function set moveEnabled(value:Boolean):void
{
if (value != _moveEnabled)
{
_moveEnabled = value;
moveEnabledChanged = true;
invalidateProperties();
dispatchEvent(new Event("moveEnabledChanged"));
}
}
This code is the hallmark of the public property API. Most of your properties will and/or should look like this. Notice some thing we have done;
- Created a place to hold the default state and updated state.
- Created a boolean flag to let all classes below that this state is changing.
- Created a simple access point publicly for the private internal state.
- Created a public place to change the state.
- For performance, check that we are not already setting a current state with the same value. (this might differ depending on implementation)
- Set our state changing flag so subclasses are aware our state is changing.
- Invalidate the component's properties, get a call to
commitProperties()on the next validation pass. - For bindable properties, dispatch an event to let listeners know we are changing state.
Below is an algorithm my framework follows and I have found it to be extremely successful in creating tighter performance and easier subclassing.
* Commits new component states.
*/
override protected function commitProperties():void
{
super.commitProperties();
if (moveEnabledChanged)
{
commitMoveEnabled();
moveEnabledChanged = false;
}
}
In the above code sample, although we are making a method call here, the performance savings down the road outweigh this one call.
Simply, the above algorithm does this;
- In component state validation.
- Call any super state changes. (this order could be reversed depending on the component's needs)
- If our move enabled state is changing
- Commit that change right now.
- The move enabled state has now changed, switch our move enabled state flag to
false.
Note :: With components you create, you will know that in the commitProperties() method that you call commitMoveEnabled(), this is the only place you will call that method. All subclasses rely on the timing of this call. Which in most cases works perfect.
* Commits all internal and dependent property states
* of ourselves and our children, plus any dependent
* listeners that rely on this state.
*/
protected function commitMoveEnabled():void
{
// proccess the new state
}
When you subclass this component, your whole move enabled protected commit API is shared. You then have the ability to aggregate private and protected delegation in a logical order starting from the first class that defined the state property.
Some subclasses might just completely override the commitMoveEnabled() method and not even call super. Some classes that define this commit method might actually supply 2 sub commit methods inside this commit method for subclasses to override on a more granular level.
* Commits all internal and dependent property states
* of ourselves and our children, plus any dependent
* listeners that rely on this state.
*/
protected function commitMoveEnabled():void
{
// proccess the new state
commitMoveListeners();
// update skins in updateDisplayList()
moveEnabledUpdateFlag = true;
invalidateDisplayList()
}
Notice in the code above, you now can subclass this class and override this method completely if you do not want the skins to be updated at this time.
{
// proccess the new state
commitMoveListeners();
}
In this subclass, you have not sacrificed the algorithm of the superclass.
Well, that is all for today. I have a bunch more to elaborate and continue with, but that is for the rest of the week.
In my commercial components, I may not release the code but, I want future customers to realize that my API is a new type of SWC. In this new world, you can subclass a component without screwing up it's parent. Plus, all methods that can extend your new product with are there for the taking.
Peace, Mike
May 8th, 2007 at 2:48 pm
Good start, Mike!
Continue to unveil the rules of building solid custom Flex 2 components with a rest of the world and the rest of the world will greatly benefit.
We were luckily to read carefully Ely Greenfield’s preso at the beginning of 2007: http://www.flex.org/ACDS/BuildingAFlexComponent.pdf
May 10th, 2007 at 1:30 pm
Great post Mike!
I have noticed this approach used in some of the native Flex components but never really saw the value of the state change flags until reading this. Very insightful.
One recommendation I would make on this post and subsequent posts is to be very clear when using the word ’state’. In this case, you are using it as a synonym for var or property, which is fine for guys who have been doing this for some time. But some newcomers might get confused as the word state also relates with the UIComponent.currentState and mx:State objects.
Thanks for the great read.
jwopitz
May 10th, 2007 at 4:42 pm
yeah,
Actually when I posted it in retrospect I thought of exactly what you are talking about. I need to find another word for ’state’. Something like ‘current property algorithm’.
I have a bunch of other things outlined that follow the same lines as these.
commitProperties() is a very powerful and underrated method in the template patter of the flex framework.
Adobe tends to actually code implementation into the commitProperties() methods. I don’t do that anymore because it tighlty couples the subclasses and you run into people complaining about private methods, properties and even plain ole rewritting the superclass method just to call something a little bit different.
Mike
June 7th, 2007 at 9:59 am
Hey Mike,
I know you are probably busy, but I thought I would let you know:
I AM EAGERLY AWAITING YOUR NEXT POST IN THIS SERIES!!!!
I haven’t been able to gather the time (nor willpower) to get back at component development or blogging.
Anywho…thanks for the great article.
jwopitz
June 7th, 2007 at 10:14 am
Hi,
I have been busy in the laboratory. Sometimes it seems like posting blog posts is harder than it actually is. If you have seen some of my components, you will understand my time is limited.
Not to mention I just finished up converting DocumentFX to apollo. That application has about 200 classes so it was a bit time consuming. I did manager to get it creating UML diagrams of class frameworks in the Flex UI.
I still havn’t decided what I am going to do with it. Would be fun to release but, for now I am just using it for my own component development docs.
Ha, maybe there are others waiting to. I will see about getting some more up.
Peace, Mike
June 7th, 2007 at 9:17 pm
E4X XML Binding & CDATA…
The benefit with using international standards when creating software is that you can blame to stupid design decisions on “an international team of brilliant computer scientists. That way, if someone tries to body-check you on the pathetic implementat…
June 19th, 2007 at 4:13 pm
Hi Mike,
Just started working on a custom and complex item renderer and I started to look back at these article for some guidance. One thing that I would like to hear you sound off on is some thoughts about the usage of the invalidateSomething methods.
They are all related to their respective calls as such:
invalidateProperties => commitProperties
invalidateDisplayList => updateDisplayList
invalidateSize => measure
I have seen similar approaches in the mx code base for using update flags for the display list. Can you talk a bit about that as well?
Thanks,
jwopitz
June 27th, 2007 at 12:16 pm
I am new to Flex and taking off like wildfire. I have been concerned about my components performance.
Thank you for helping me realize the errors of my noob ways!
Nice set of code and framework. I will be considering your components for my applications as they mature.
Thanks again,
Tony
June 27th, 2007 at 1:16 pm
Mike,
Sorry for the double post, but you have to know how you just saved my @$$!
I wrote my last comment only after reading your article. I applied into real time and ran my application for the first time just seconds ago. WOW!!!!
I think I will be spending the rest of the day rewriting about 2,000 lines of code.
Here was my mistake….
I was creating a public property that was bindable in my control. Binding it to my child controls in multiple places. I changed it to the process above and nearly fell off my chair. Not to mention it fixed a couple timing issues that I could not get rid of from my previous process. Ignorance is not always Bliss.
The kicker is that I was binding to bitmap classes that were being embedded. Who knows how many times the application reapplied the binding before finishing.
I hope you post the rest of the articles soon, so I can rewrite some more code.
You DA MAN!!!
Regards,
Tony
July 24th, 2007 at 5:55 pm
[…] Mike: http://www.flex2components.com/f2cblog/2007/05/08/flex-commitproperties-a-components-state-queue/ http://www.flex2components.com/f2cblog/2007/06/19/flex-invalidatethis-big-bird/ […]