Building Components In Flex3
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Building Components In Flex3

  • 3,331 views
Uploaded on

Building Components in Flex3 is the topic of July 2009's Flex group meeting @ tikalk

Building Components in Flex3 is the topic of July 2009's Flex group meeting @ tikalk

More in: Technology , Business
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
3,331
On Slideshare
3,267
From Embeds
64
Number of Embeds
5

Actions

Shares
Downloads
101
Comments
0
Likes
3

Embeds 64

http://www.tikalk.com 44
http://www.slideshare.net 12
http://www.tikalk.tikalknowledge.com 5
http://tikalk.tikalknowledge.com 2
http://tikalk.com 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • 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.

Transcript

  • 1. Creating Custom Components in Flex 3
  • 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( "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();
    • }
  • 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