• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Building Components In Flex3
 

Building Components In Flex3

on

  • 3,110 views

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

Statistics

Views

Total Views
3,110
Views on SlideShare
3,046
Embed Views
64

Actions

Likes
3
Downloads
101
Comments
0

5 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

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • 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.

Building Components In Flex3 Building Components In Flex3 Presentation Transcript

  • 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