SlideShare a Scribd company logo
Creating Custom Components in Flex 3
Vocab Lesson  Flex Component Lifecycle A mechanism the framework uses to create, manage and destroy components A mechanism that makes the most of the player rendering model.  Halo:   Component architecture used in Flex 3 and earlier versions.
Halo Component Architecture Patterns  Defining Patterns in Halo Invalidation/Validation Model  Methodology to  aggregate  changes and  defer  work until an optimal later time  Event Driven Interaction Model  Inform the component if something is about to or has already occurred  Composition  Parameterization of a component’s appearance or content.  Most often occurs through factories and item renderers.
Invalidation / Validation theory Flash player  Rendering model
Flash player frames The Flash Player runs through each frame of a timeline one by one at a speed determined by the frame rate (fps) Each frame consists of executing ActionScript code and rendering FP5  allow executing actionscript when a particular events occur EnterFrame is fired when a frame begins Frame rate is configurable (compiled with the swf) but is limited by browser/Os
Flash player frames On one hand : Flex application consists on 2 frames On the other hand : enterFrame event is continuously fired ? Question ?
Flash player frames ! Answer !
The Elastic Racetrack  Flex component lifecycle is built atop this frame model Invalidation/Validation takes advantage of the elastic racetrack to get work done in an efficient manner. Images courtesy of Sean Christmann Traditional Flash Player Elastic Racetrack
The Elastic Racetrack  Images courtesy of Sean Christmann User Actions •  Interact with any non-  validation events from this frame (mouse movements, timers,  ENTER_FRAME s etc.) •  Dispatch invalidation events (invalidateProperties etc.) Invalidate Action •  Process all validation calls (CommitProperties) Render Action •  Do the heavy lifting - actually draw on the screen Event.updateAfterEvent -> Stage.Invalidate->Render event->Validation methods
Deferred Validation Model Waiting for update request Update Requested Invalidation Validation Validation occurs right before Rendering Invalidation Validation
Halo Component Lifecycle – Broken Down  3 Phase Lifecycle Initialization (Birth) Construction Configuration Attachment Initialization Updating  (Life) Component responds to changes by using the Invalidation/Validation Model  - Interaction -> invalidation - > validation Destruction (Death) Out of sight, out of mind  Detachment  Garbage collection
Consider this component: public class A extends UIComponent { public function A() { trace( "CONSTRUCTOR" ); super(); } override protected function createChildren() : void { trace( "CREATECHILDREN" ); super.createChildren(); } override protected function measure() : void { trace( "MEASURE" ); super.measure(); } override protected function updateDisplayList(width:Number, height:Number) : void { trace( "UPDATEDISPLAYLIST" ); super.updateDisplayList(width,height); } override protected function commitProperties():void { trace( "COMMITPROPERTIES" ); super.commitProperties(); }
Lifecycle Phase 1: Initialization  Construction: Component begins its lifecycle  Component is instantiated (create in memory), through the  new  operator in ActionScript or in MXML No required arguments (if it will be used in MXML); zero, or all optional  Calls super() to invoke superclass constructor; if you don’t, the compiler will! Constructor can add event listeners, hard code initialization properties of super classes Have access to class properties and methods Children have not yet been created! Minimal work should occur here (not JIT’ed). Don’t create or attach children in the constructor   Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death)
Lifecycle Phase 1: Initialization  Configuration: Component properties are set internally to be processed later In  MXML , properties are assigned in this phase, before children are attached or initialized. Sample.mxml wants to expose a  text  property to update the label <mx:Canvas> <mx:Label id=&quot;myLabel&quot;/> </mx:Canvas> Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death) <mx:Application ...> ... <local:Sample text=&quot;value!&quot;/> </mx:Application> Output: Sample constructor Sample.text setter Adding Sample to display list (which creates myLabel)
Lifecycle Phase 1: Initialization  Properties must expect that children haven’t been created yet. Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death) Bad: public function set text(value:String):void } myLabel.text = value; // Possible Error! during first config phase, // myLabel might not exist! {
Lifecycle Phase 1: Initialization  In ActionScript, properties  might  be assigned in this phase, before children are attached or initialized Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death) //Developer might code this: var comp: SampleChild = new SampleChild(); addChild(comp); comp.property1 = value1; //off the hook //Or this: var comp: SampleChild = new SampleChild(); comp.property1 = value1; //throw exception addChild(comp); Exception in case the property try to access a child
Lifecycle Phase 1: Initialization  To avoid performance bottlenecks, make your setters fast and defer any real work until validation using invalidatin/validation Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death) Good : private var _text:String = &quot;&quot;; private var textChanged:boolean = false; public function set text(value:String):void } _text = value;  //store textChanged = true;  //mark invalidateProperties();  //invalidate invalidateSize(); invalidateDisplayList(); } override protected function commitProperties():void{ super.commitProperties(); if(textChanged) {   myLabel.text = text;   textChanged = false;} // don’t forget to unmark !!! { }
Lifecycle Phase 1: Initialization  Attachment : Addition to the display list  Component is added to the display list through addChild, addChildAt, MXML declaration.  Without attachment, component lifecycle will stall.  Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death) <mx:Application ...> <mx:Script> <![CDATA[ override protected function createChildren() : void  { super.createChildren(); var a : A = new A();  Output: CONSTRUCTOR this.addChild( a );    CREATECHILDREN }   ]]> </mx:Script> </mx:Application>  COMMITPROPERTIES MEASURE UPDATEDISPLAYLIST CREATIONCOMPLETE Moral of the story: don’t add components to the stage until you need them.
Lifecycle Phase 1: Initialization  Initialization main steps ( not all of them !  full list ) preinitialize  event is dispatched createChildren() is called Calling   invalidation   methods initialize  event is dispatched  First full  validation  pass occurs creationComplete  event is dispatched  Full invalidation/validation cycle is invoked (we will come back to this)    Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death) Create Validate
Lifecycle Phase 1: Initialization  createChildren()  - The attachment workhorse  Ideal place for adding children that are required throughout the lifetime of the component  Dynamic or data-driven children which should be added in  commitProperties()   Check to make sure the children have not been instantiated already Follow the same pattern Flex uses: construct, configure, attach.  if (!stopButton) } stopButton = new Button(); stopButton.label = &quot;stop&quot;; stopButton.addEventListener(MouseEvent.CLICK,stopBtnClickHandler); controlBar.addChild(stopButton); {   Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death) Construct Configure Attach
Lifecycle Phase 1: Initialization  First full invalidation/validation pass occurs here Invalidation is captured by 3 methods: invalidateProperties() invalidateSize() invalidateDisplayList() Validation is captured by 3 methods: commitProperties() measure() updateDisplayList()  Phase 1 Done!   Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death)
Phase 2: Updating Our component has been created!  It’s a living, breathing entity, and now it needs to know how to update.  Updates occur When a user interacts with a component When methods or properties are invoked/set  A component should use Flex’s Invalidation/Validation Model to respond to changes.    Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death)
Deferred Validation Model: An Optimization  Invalidation/validation model is split into 3 phases: Update component properties Update sizing & measurement information Update drawing and positioning invalidateProperties()  invalidateSize()  invalidateDisplayList()  commitProperties() measure() updateDisplayList()
commitProperties() Property management phase of validation Purpose : Commit values typically set using a property setter Invoked by the framework before measurement and layout.  There is a definite pattern that should be followed in order to avoid extra work.  Dirty flags and storage variables  This is the place to add/remove children  not  required through the life of the entire component (as opposed to  createChildren() ) Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death)
Invalidation/Validation example The idea : bind a list of labels to an array. The list will add a label to the display list for each item in the array. <mx:Application > <mx:Script> <![CDATA[ import  mx . collections . ArrayCollection ; [ Bindable ] public  var  arr : ArrayCollection =  new  ArrayCollection() ; public  function  onClick() :  void { var  c : int =  0; while ( c++ <  20  ) { arr . addItem( c ) ; //add 20 items to the array collection } } ]]> </mx:Script> <mx:VBox> <mx:Button  label=&quot; Click me! &quot; click=&quot; onClick() &quot; /> <test:BadList  id=&quot; theList &quot; dataProvider=&quot; { arr } &quot; /> //the list creates a label for each entity in the array </mx:VBox> </mx:Application>
Invalidation/Validation Bad implementation  public  class  BadList  extends  VBox } private  var  _dataProvider : ArrayCollection; public  function  set  dataProvider( arr : ArrayCollection ) :  void  { this ._dataProvider = arr; arr.addEventListener( CollectionEvent . COLLECTION_CHANGE, dataProviderChangeHandler ); } private  function  dataProviderChangeHandler( e : Event ) :  void { this .removeAllChildren(); for each (  var  n : Number  in this ._dataProvider ) { var  l : Label =  new  Label(); l.text = n.toString(); this .addChild( l ); } } }   Result: dataProviderChangeHandler called 20 times
Invalidation/Validation Good implementation  public class GoodList extends VBox } private var _dataProvider : ArrayCollection; private var _dataProviderChanged : Boolean = false; public function  set dataProvider ( arr : ArrayCollection ) : void { This.dataProvider = arr; arr.addEventListener( CollectionEvent.COLLECTION_CHANGE, dataProviderChangeHandler ); dataProviderChanged = true; invalidateProperties(); } override protected function commitProperties():void { super.commitProperties(); if( dataProviderChanged ) { removeAllChildren(); for each( var n : Number in this._dataProvider ) { var l : Label = new Label(); l.text = n.toString(); addChild( l );   } this._dataProviderChanged = false;   } } private function dataProviderChangeHandler( e : Event ) : void { dataProviderChanged = true; invalidateProperties(); }   Result: commitProperties called only twice (once during initialization)
measure() Sizing phase of validation Purpose : Component can calculate its ‘natural’/preferred/default size based on content and layout rules. Implicitly invoked when component children change size. (Don’t call  measure()  on your children).  Measurement occurs from the bottom up.  <mx:Application> <mx:HBox>   <mx:Button /> </mx:HBox> </mx:Application> Don’t count on it: Framework optimizes away unnecessary calls to  measure() . Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death)
Overriding measure() Used for dynamic layout containers (Vbox etc.) Use  getExplicitOrMeasuredWidth()  for children which are UiComponents Use  width  for non UiComponents ALWAYS called during initialization Call super.measure() first! Set  measuredHeight ,  measuredWidth  for the default values;  measuredMinHeight and  measuredMinWidth  for the minimum. Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death) To get up and running fast, explicitly size your component.
measure() example override protected function measure( ):void } super.measure( ); measuredHeight = measuredMinHeight = currentIcon.height; measuredWidth = measuredMinWidth = currentIcon.width +    displayNameLabel.getExplicitOrMeasuredWidth( ); { Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death)
updateDisplayList() Layout and Drawing Phase of Invalidation  Purpose : Lay out component contents and perform any drawing Layout and positioning occurs from the top down, given:  <mx:Application> <mx:HBox>   <mx:Button /> </mx:HBox> </mx:Application> super() is optional - don’t call it if you’re overriding everything it does Size and lay out children If the child is a UIComponent, size it with  setActualSize()  and position it with  move() If the child is not a UIComponent, set the x, y, width and height properties.  Good place to use Flash Player Drawing API  Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death)
updateDisplayList() example override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth,unscaledHeight); displayNameLabel.move(currentIcon.x + currentIcon.width,0); displayNameLabel.setActualSize(unscaledWidth-currentIcon.width, unscaledHeight); { Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death)
Phase 3: Destruction  Destroying the component  Detachment: Remove the component from the display list Components do not get validated or drawn when off the display list  Once off the display list:  You can re-parent the component, and it will be brought back to life.  Re-parenting is cheaper then re-instantiating a component  Garbage Collection No active references can be tough Common culprits include event listeners, dictionaries and timers.    Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection   Initialization (Born) Updating (Life) Destruction (Death)
In Conclusion… Flash Player Elastic Racetrack: Learn it, love it, live it.  Invalidation: All the cool kids are doing it.  The best component lifecycle reference is right in front of you: Read Framework Code.  Resources Elastic Racetrack Updated Elastic Racetrack Building custom components  (ppt, source, video) Diving deep with Flex component lifecycle

More Related Content

Building Components In Flex3

  • 2. Vocab Lesson Flex Component Lifecycle A mechanism the framework uses to create, manage and destroy components A mechanism that makes the most of the player rendering model. Halo: Component architecture used in Flex 3 and earlier versions.
  • 3. Halo Component Architecture Patterns Defining Patterns in Halo Invalidation/Validation Model Methodology to aggregate changes and defer work until an optimal later time Event Driven Interaction Model Inform the component if something is about to or has already occurred Composition Parameterization of a component’s appearance or content. Most often occurs through factories and item renderers.
  • 4. Invalidation / Validation theory Flash player Rendering model
  • 5. Flash player frames The Flash Player runs through each frame of a timeline one by one at a speed determined by the frame rate (fps) Each frame consists of executing ActionScript code and rendering FP5 allow executing actionscript when a particular events occur EnterFrame is fired when a frame begins Frame rate is configurable (compiled with the swf) but is limited by browser/Os
  • 6. Flash player frames On one hand : Flex application consists on 2 frames On the other hand : enterFrame event is continuously fired ? Question ?
  • 7. Flash player frames ! Answer !
  • 8. The Elastic Racetrack Flex component lifecycle is built atop this frame model Invalidation/Validation takes advantage of the elastic racetrack to get work done in an efficient manner. Images courtesy of Sean Christmann Traditional Flash Player Elastic Racetrack
  • 9. The Elastic Racetrack Images courtesy of Sean Christmann User Actions • Interact with any non- validation events from this frame (mouse movements, timers, ENTER_FRAME s etc.) • Dispatch invalidation events (invalidateProperties etc.) Invalidate Action • Process all validation calls (CommitProperties) Render Action • Do the heavy lifting - actually draw on the screen Event.updateAfterEvent -> Stage.Invalidate->Render event->Validation methods
  • 10. Deferred Validation Model Waiting for update request Update Requested Invalidation Validation Validation occurs right before Rendering Invalidation Validation
  • 11. Halo Component Lifecycle – Broken Down 3 Phase Lifecycle Initialization (Birth) Construction Configuration Attachment Initialization Updating (Life) Component responds to changes by using the Invalidation/Validation Model - Interaction -> invalidation - > validation Destruction (Death) Out of sight, out of mind Detachment Garbage collection
  • 12. Consider this component: public class A extends UIComponent { public function A() { trace( &quot;CONSTRUCTOR&quot; ); super(); } override protected function createChildren() : void { trace( &quot;CREATECHILDREN&quot; ); super.createChildren(); } override protected function measure() : void { trace( &quot;MEASURE&quot; ); super.measure(); } override protected function updateDisplayList(width:Number, height:Number) : void { trace( &quot;UPDATEDISPLAYLIST&quot; ); super.updateDisplayList(width,height); } override protected function commitProperties():void { trace( &quot;COMMITPROPERTIES&quot; ); super.commitProperties(); }
  • 13. Lifecycle Phase 1: Initialization Construction: Component begins its lifecycle Component is instantiated (create in memory), through the new operator in ActionScript or in MXML No required arguments (if it will be used in MXML); zero, or all optional Calls super() to invoke superclass constructor; if you don’t, the compiler will! Constructor can add event listeners, hard code initialization properties of super classes Have access to class properties and methods Children have not yet been created! Minimal work should occur here (not JIT’ed). Don’t create or attach children in the constructor Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death)
  • 14. Lifecycle Phase 1: Initialization Configuration: Component properties are set internally to be processed later In MXML , properties are assigned in this phase, before children are attached or initialized. Sample.mxml wants to expose a text property to update the label <mx:Canvas> <mx:Label id=&quot;myLabel&quot;/> </mx:Canvas> Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death) <mx:Application ...> ... <local:Sample text=&quot;value!&quot;/> </mx:Application> Output: Sample constructor Sample.text setter Adding Sample to display list (which creates myLabel)
  • 15. Lifecycle Phase 1: Initialization Properties must expect that children haven’t been created yet. Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death) Bad: public function set text(value:String):void } myLabel.text = value; // Possible Error! during first config phase, // myLabel might not exist! {
  • 16. Lifecycle Phase 1: Initialization In ActionScript, properties might be assigned in this phase, before children are attached or initialized Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death) //Developer might code this: var comp: SampleChild = new SampleChild(); addChild(comp); comp.property1 = value1; //off the hook //Or this: var comp: SampleChild = new SampleChild(); comp.property1 = value1; //throw exception addChild(comp); Exception in case the property try to access a child
  • 17. Lifecycle Phase 1: Initialization To avoid performance bottlenecks, make your setters fast and defer any real work until validation using invalidatin/validation Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death) Good : private var _text:String = &quot;&quot;; private var textChanged:boolean = false; public function set text(value:String):void } _text = value; //store textChanged = true; //mark invalidateProperties(); //invalidate invalidateSize(); invalidateDisplayList(); } override protected function commitProperties():void{ super.commitProperties(); if(textChanged) { myLabel.text = text; textChanged = false;} // don’t forget to unmark !!! { }
  • 18. Lifecycle Phase 1: Initialization Attachment : Addition to the display list Component is added to the display list through addChild, addChildAt, MXML declaration. Without attachment, component lifecycle will stall. Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death) <mx:Application ...> <mx:Script> <![CDATA[ override protected function createChildren() : void { super.createChildren(); var a : A = new A(); Output: CONSTRUCTOR this.addChild( a ); CREATECHILDREN } ]]> </mx:Script> </mx:Application> COMMITPROPERTIES MEASURE UPDATEDISPLAYLIST CREATIONCOMPLETE Moral of the story: don’t add components to the stage until you need them.
  • 19. Lifecycle Phase 1: Initialization Initialization main steps ( not all of them ! full list ) preinitialize event is dispatched createChildren() is called Calling invalidation methods initialize event is dispatched First full validation pass occurs creationComplete event is dispatched Full invalidation/validation cycle is invoked (we will come back to this) Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death) Create Validate
  • 20. Lifecycle Phase 1: Initialization createChildren() - The attachment workhorse Ideal place for adding children that are required throughout the lifetime of the component Dynamic or data-driven children which should be added in commitProperties() Check to make sure the children have not been instantiated already Follow the same pattern Flex uses: construct, configure, attach. if (!stopButton) } stopButton = new Button(); stopButton.label = &quot;stop&quot;; stopButton.addEventListener(MouseEvent.CLICK,stopBtnClickHandler); controlBar.addChild(stopButton); { Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death) Construct Configure Attach
  • 21. Lifecycle Phase 1: Initialization First full invalidation/validation pass occurs here Invalidation is captured by 3 methods: invalidateProperties() invalidateSize() invalidateDisplayList() Validation is captured by 3 methods: commitProperties() measure() updateDisplayList() Phase 1 Done! Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death)
  • 22. Phase 2: Updating Our component has been created! It’s a living, breathing entity, and now it needs to know how to update. Updates occur When a user interacts with a component When methods or properties are invoked/set A component should use Flex’s Invalidation/Validation Model to respond to changes. Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death)
  • 23. Deferred Validation Model: An Optimization Invalidation/validation model is split into 3 phases: Update component properties Update sizing & measurement information Update drawing and positioning invalidateProperties() invalidateSize() invalidateDisplayList() commitProperties() measure() updateDisplayList()
  • 24. commitProperties() Property management phase of validation Purpose : Commit values typically set using a property setter Invoked by the framework before measurement and layout. There is a definite pattern that should be followed in order to avoid extra work. Dirty flags and storage variables This is the place to add/remove children not required through the life of the entire component (as opposed to createChildren() ) Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death)
  • 25. Invalidation/Validation example The idea : bind a list of labels to an array. The list will add a label to the display list for each item in the array. <mx:Application > <mx:Script> <![CDATA[ import mx . collections . ArrayCollection ; [ Bindable ] public var arr : ArrayCollection = new ArrayCollection() ; public function onClick() : void { var c : int = 0; while ( c++ < 20 ) { arr . addItem( c ) ; //add 20 items to the array collection } } ]]> </mx:Script> <mx:VBox> <mx:Button label=&quot; Click me! &quot; click=&quot; onClick() &quot; /> <test:BadList id=&quot; theList &quot; dataProvider=&quot; { arr } &quot; /> //the list creates a label for each entity in the array </mx:VBox> </mx:Application>
  • 26. Invalidation/Validation Bad implementation public class BadList extends VBox } private var _dataProvider : ArrayCollection; public function set dataProvider( arr : ArrayCollection ) : void { this ._dataProvider = arr; arr.addEventListener( CollectionEvent . COLLECTION_CHANGE, dataProviderChangeHandler ); } private function dataProviderChangeHandler( e : Event ) : void { this .removeAllChildren(); for each ( var n : Number in this ._dataProvider ) { var l : Label = new Label(); l.text = n.toString(); this .addChild( l ); } } } Result: dataProviderChangeHandler called 20 times
  • 27. Invalidation/Validation Good implementation public class GoodList extends VBox } private var _dataProvider : ArrayCollection; private var _dataProviderChanged : Boolean = false; public function set dataProvider ( arr : ArrayCollection ) : void { This.dataProvider = arr; arr.addEventListener( CollectionEvent.COLLECTION_CHANGE, dataProviderChangeHandler ); dataProviderChanged = true; invalidateProperties(); } override protected function commitProperties():void { super.commitProperties(); if( dataProviderChanged ) { removeAllChildren(); for each( var n : Number in this._dataProvider ) { var l : Label = new Label(); l.text = n.toString(); addChild( l ); } this._dataProviderChanged = false; } } private function dataProviderChangeHandler( e : Event ) : void { dataProviderChanged = true; invalidateProperties(); } Result: commitProperties called only twice (once during initialization)
  • 28. measure() Sizing phase of validation Purpose : Component can calculate its ‘natural’/preferred/default size based on content and layout rules. Implicitly invoked when component children change size. (Don’t call measure() on your children). Measurement occurs from the bottom up. <mx:Application> <mx:HBox> <mx:Button /> </mx:HBox> </mx:Application> Don’t count on it: Framework optimizes away unnecessary calls to measure() . Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death)
  • 29. Overriding measure() Used for dynamic layout containers (Vbox etc.) Use getExplicitOrMeasuredWidth() for children which are UiComponents Use width for non UiComponents ALWAYS called during initialization Call super.measure() first! Set measuredHeight , measuredWidth for the default values; measuredMinHeight and measuredMinWidth for the minimum. Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death) To get up and running fast, explicitly size your component.
  • 30. measure() example override protected function measure( ):void } super.measure( ); measuredHeight = measuredMinHeight = currentIcon.height; measuredWidth = measuredMinWidth = currentIcon.width + displayNameLabel.getExplicitOrMeasuredWidth( ); { Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death)
  • 31. updateDisplayList() Layout and Drawing Phase of Invalidation Purpose : Lay out component contents and perform any drawing Layout and positioning occurs from the top down, given: <mx:Application> <mx:HBox> <mx:Button /> </mx:HBox> </mx:Application> super() is optional - don’t call it if you’re overriding everything it does Size and lay out children If the child is a UIComponent, size it with setActualSize() and position it with move() If the child is not a UIComponent, set the x, y, width and height properties. Good place to use Flash Player Drawing API Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death)
  • 32. updateDisplayList() example override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth,unscaledHeight); displayNameLabel.move(currentIcon.x + currentIcon.width,0); displayNameLabel.setActualSize(unscaledWidth-currentIcon.width, unscaledHeight); { Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death)
  • 33. Phase 3: Destruction Destroying the component Detachment: Remove the component from the display list Components do not get validated or drawn when off the display list Once off the display list: You can re-parent the component, and it will be brought back to life. Re-parenting is cheaper then re-instantiating a component Garbage Collection No active references can be tough Common culprits include event listeners, dictionaries and timers. Construction Configuration Attachment Initialization Invalidation Validation Detachment Garbage Collection Initialization (Born) Updating (Life) Destruction (Death)
  • 34. In Conclusion… Flash Player Elastic Racetrack: Learn it, love it, live it. Invalidation: All the cool kids are doing it. The best component lifecycle reference is right in front of you: Read Framework Code. Resources Elastic Racetrack Updated Elastic Racetrack Building custom components (ppt, source, video) Diving deep with Flex component lifecycle

Editor's Notes

  1. Who am I, what do I do? What are we going to cover? – component lifecycle in Flex 3 and Gumbo What are we not going to cover? Fx prefixing, why we make things in the framework private, Flash on the iPhone, etc, etc – I’m around afterwards to discuss all that Pace: 35/15/10 Give out a few books.