Flex4 component lifecycle
description
Transcript of Flex4 component lifecycle
Flex 4 Component Lifecycle
1
RJ Owen (or perhaps Tony Hillerson, if I’m called in for jury duty.)
Flash Camp Denver
10.12.2010
2
Who am I?Senior Software Architect @ EffectiveUI
Blogger for InsideRIA
Adobe Community Expert in Flex
Lead developer on some cool projects for cool clients (just like you.)
3
Who are you?Software Developers, perhaps Designers
Experienced in Flex 3?
Interested in building better interfaces
Interested in performance
4
What will we talk about today?What is Flex?
Frames, and how to slice them
Flex 4 component theory
Flex 4 component life-cycle
5
What is Flex anyway?A FRAMEWORK built on top of Flash - content for the Flash player and AIR runtime
A declarative Flash content language - MXML
An expanding and evolving set of components
A framework for displaying and managing components• The LayoutManager• The Component Lifecycle
You could do all of this in Flash (authoring)! (It would take longer.)
6
The Flash Timeline
timeline image: www.jaanuskase.com
All flash-platform content is FRAME-BASED
Frames execute one after another, over and over, forever and ever.
Slicing a Frame
7
During each frame, the appropriate player / runtime will:‣ Execute Code (process)‣ Render to the screen (draw)
This continues for every frame in the Flash movie or AIR application.
Processing Drawing
1 2 3 n
A Frame
Frames that take too long
8
1 2 3 n
1 2 3 n
When frames spend too much time processing or rendering, “stretching” occurs.
This causes the frame-rate to drop (fewer frames are rendered per second), making your application slow, choppy and less responsive.
This is often referred to as the “elastic racetrack.”
racetrack image:Ted Patrick, http://ted.onflash.org/2005/07/flash-player-mental-model-elastic.php
Three Slices
9
Player Events
UserCode
Prerender Event
User Code
Player Render
User Action Invalidate Action Render Action
Frame image and everything I know about the frame model: Sean Christmann, http://www.craftymind.com/2008/04/18/updated-elastic-racetrack-for-flash-9-and-avm2/
Frames aren’t really that simple. The Flash Player runs on event loops.
Loops vary in time from ~5ms to ~20ms (see Sean Christmann’s research on this) depending on code execution and rendering time.
Event loops process the user action, invalidate action, and render action in that order.
Each frame is built of combinations of these slices, depending on the frame rate.
Frame 1 Frame 2 Frame 3 Frame 4 Frame 5
Frames can contain multiple slices
10
Frame 1 Frame 2 Frame 3 Frame 4 Frame 5 Frame 6 Frame 7 Frame 8 Frame 9 Frame 10
5 fps compiled framerate
25 fps compiled framerate
50 fps compiled framerate
Frame 1
Sean assumes ~20ms slices. In that case, a framerate of 5 fps yields 9 processing-only frames and 1 processing+render frame.
25fps gives 1 processing frame and 1 processing + rendering; at 50 fps we render with each slice (20ms = .002s; 50 fps * .002s = 1 frame)
http://www.austinkleon.com/2008/04/21/so-what/
The point is that Flex runs in these frames, and we need to make the most of them.
You may go through multiple processing slices before you get to render
Flex components and the framework itself are built around the frame model. Flex components help optimize your application for performance through....
THE COMPONENT LIFECYCLE!
Understanding frames and slices is key to understanding the value of the lifecycle.
12
FLEX RUNS IN FRAMES
13
FLEX 4 COMPONENT THEORYA little on why Flex 4 components are different
14
Components: What are they?Contained bits of functionality
Controls displayed on the screen
Containers for those controls
Highly VisualExamples: Button, ComboBox, List
15
Components: what’s broken?In Halo (Flex 3), components were rigid
Hard to extend
“Monkey patching” to make small changes to component view
Example: HTML text in the panel title bar
16
Flex 4 Components: Issues to addressSeparate data, logic and behavior from visuals, states, animation and layout
Create component-logic with no assumption about appearance
Create component-view without digging into the logic
17 MVC in a button component
label:String, selected:Boolean
text field, icon, background
mouse handlers, selection logic
18
Flex 3 Components (Halo)
Component
Skin (background)
19
Flex 4 Components (Spark)
Component
Skin (entire view)
20
Skin PartsComponent specifies optional/required skin parts as metadata [SkinPart(required=”true”)] public var labelElement:SimpleText;
Skin implements skin parts
Exception thrown if required part is not found
Component should set data on skin parts in the setters AND component.partAdded(); method
21
Skin StatesDefined in the component using metadata[SkinState(“up”)][SkinState(“down”)]
Current state is passed to the skin from the component
All states are required. An exception will be thrown if a state is not implemented in the skin
Skins are Components tooYour component has one child in it’s display list: your Skin class
All other elements (skin parts, component children) are added to the Skin’s child list in different display objects, which are made accessible as your Component’s elements list.
22
Skin
Group
GroupBase
UIComponent
SkinnableComponent
23
FLEX 4 COMPONENT LIFE-CYCLEAn in-depth look at the life and times of today’s modern component
24
Flex 4 Component LifecycleWhat is it?The way the framework interacts with every Flex componentA set of methods the framework calls to instantiate, control, and destroy componentsMethods that make the most of every frame
25 Flex 4 Components are built on Flex 3 Components
Flex 3 Component Model (Halo)
Flex 4 Component Model (Spark)
UIComponent
Skinnable Component
Flex 3 Component Model (Halo)
Flex 4 Component Model (Spark)
26
Flex 4 Component Lifecycle: 3 Stages
Construction
Configuration
Addition
Initialization
Invalidation
Validation
Interaction
Removal
Garbage Collection
Birth
Life
Death
27
Birth: ConstructionCalls your constructor
Can access properties and methods of the class, but note that children have not been created yet!!
Must be public, no return type
Call super();
Not used often in Flex
Construction
Configuration
Addition
Initialization
var theLabel : Label = new Label();<mx:Label id="theLabel"/>
28
Birth: ConstructionJIT: “Just In Time” compilation. The VM will compile AS3 bytecode down to native machine code for your target platform.
Constructors are NEVER JIT compiled, so putting code in your constructor is less efficient in terms of swf size than keeping it elsewhere.
Most everything else in the framework IS JIT’d, and there’s a place in the lifecycle for most everything else you’ll need.
If you want to assign listeners at this stage, put them in a separate method so JIT compilation can occur.
Your takeaway: keep your constructors slim.
Construction
Configuration
Addition
Initialization
29
Birth: ConfigurationThe process of assigning values to properties on objects
This results in the first call to commitProperties();
Containers must not expect children to be added yet
For optimization, make setters fast and DEFER the real work until validation (more later)
Until attachment occurs and your component is added to a display list, things stall here. Your component is in memory and it has values assigned to its properties, but it’s not visible and won’t go through the rest of the life cycle.
<local:SampleChild property1="value!"/>
Construction
Configuration
Addition
Initialization
30
Birth: AttachmentAdding a component to the display elements list parent.addElement(yourComponent);
Construction
Configuration
Addition
Initialization
31
Attachment: Element ListsEvery component on the screen lives in a Display List
Components are added to display lists
Graphical Elements (rectangles, circles, text, etc.) are DRAWN into other Components
True components are still on the child list
Flex 4 lets us treat graphical elements as first class citizens (like components), but we need display objects that inherit from UIComponent to draw them on.
The Elements List abstracts the components created to draw graphics for us - we use it like the child list, but it’s not the same thing. Graphics are DRAWN into children while components ARE children, yet they’re all elements.
Construction
Configuration
Addition
Initialization
32 Attachment: DisplayObject Sharing
Group(DisplayObject)
Rect
Rect
Path
Rect
RectRotation=90
UIComponent(DisplayObject)
Elements
Ellipse
Label
32 Attachment: DisplayObject Sharing
Group(DisplayObject)
Rect
Rect
Path
Rect
RectRotation=90
UIComponent(DisplayObject)
Elements
Ellipse
Label
Draw Into
32 Attachment: DisplayObject Sharing
Group(DisplayObject)
Rect
Rect
Path
Rect
RectRotation=90
UIComponent(DisplayObject)
Elements
Ellipse
Label
Children
Draw Into
32 Attachment: DisplayObject Sharing
Group(DisplayObject)
Rect
Rect
Path
Rect
RectRotation=90
UIComponent(DisplayObject)
Elements
Ellipse
Label
Sprite
Children
Draw Into
Draw Into
32 Attachment: DisplayObject Sharing
Group(DisplayObject)
Rect
Rect
Path
Rect
RectRotation=90
UIComponent(DisplayObject)
Elements
Ellipse
Label
Sprite
Sprite
Children
Draw Into
Draw Into
Draw Into
32 Attachment: DisplayObject Sharing
Group(DisplayObject)
Rect
Rect
Path
Rect
RectRotation=90
UIComponent(DisplayObject)
Elements
Ellipse
Label
Sprite
Sprite
Sprite
Children
Draw Into
Draw Into
Draw Into
Draw Into
Birth: Initialization
33
After attachment, it’s time to initialize your component.Initialization involves several method calls and dispatches several events.
Birth: Initialization
Component Skin
Create children, do first validation pass
initialize();
createChildren();
preInitialize event dispatched!
initializeAccessibility();
initializeComplete();
initialize event dispatched!
childrenCreated();
validateSkinChange();
attachSkin();
findSkinParts();
partAdded();
constructor();
initialize();
getCurrentSkinState(); currentState = ...
measure(); / updateDisplayList(); commitProperties(); / measure(); / updateDisplayList();
creationComplete event dispatched!
35
LifeAfter initialization, we’re ready to go
The component is added to the screen and available to users
User interaction should cause changes in components – set invalidation flags
When the next Render event occurs, validation methods will be called
Invalidation
Validation
Interaction
36
Life: DefermentThe invalidation process:When a property is set, retain the value on a private variableSet a “dirty” flagInvalidate the Component
The validation process:When the framework calls validation methods, update your component accordingly
Example: set “Text” on the TextBase class
public function set text(value:String):void { if (value != _text) { _text = value;
invalidateTextLines(); invalidateSize(); invalidateDisplayList(); } }
37
Life: Invalidation
Invalidation
Validation
Interaction
Player Events
UserCode
Prerender Event
User Code
Player Render
User Action Invalidate Action Render Action
Invalidation Occurs Here
38
Life: InvalidationInvalidation Methods
Called to “invalidate” a component, but not do any work on it
invalidateProperties() • any property changes
invalidateSize()• changes to width or height
invalidateDisplayList()• changes to child elements - either their size or position - or data provider (if applicable.)
invalidateSkinState()• Just sets skinChanged=true;• Calls invalidateProperties();
Invalidation
Validation
Interaction
39
Life: Validation
Invalidation
Validation
Interaction
Player Events
UserCode
Prerender Event
User Code
Player Render
User Action Invalidate Action Render Action
Validation Occurs Here
40
Life: Validation“Do the work” that invalidation requires
Move things, add things, remove things, etc.
The goal: don’t duplicate or re-do things in the same frame
commitProperties()
getCurrentSkinState()
updateDisplayList()
measure()
Invalidation
Validation
Interaction
commitProperties()
41
Invoked first - immediately before measurement and layout
ALL changes based on property and data events go here
Even creating and destroying children, so long as they’re based on changes to properties or underlying data
Example: any list based component with empty renderers on the screen
getCurrentSkinState()
42
Used if the skin state needs to be updated based on a change to the component
Override this in your components to provide the proper skin state - it’s a worthless method in SkinnableContainer.
Necessary moving forward when skin states will vary depending on interaction modes, but otherwise this isn’t very important
Example: mobile components have no “over” state.
measure()
43
Component calculates its preferred (“default”) and minimum proportions based on content, layout rules, constraints.
Measure is called bottom up - lowest children first
Caused by “invalidateSize()”
NEVER called for explicitly sized components
overriding measure()
44
In Flex 3 this was very important for container components.
In Flex 4, consider using a layout if you find yourself needing to override measure.
Use getExplicitOrMeasuredWidth() (or height) to get child proportions
ALWAYS called during initialization, but not necessarily after that. The framework optimizes away calls to measure that aren’t “necessary.”
Call super.measure() first!
Set measuredHeight, measuredWidth for the default values; measuredMinHeight and measuredMinWidth for the minimum.
updateDisplayList()
45
Used when elements on the elements / display lists need to be drawn
In Flex 3 this was a major component of layout containers - now we use Layout objects and skin classes, so this is less important
Try not to override this on your component - first examine if perhaps the logic should be in the skin class instead.
Sometimes you will need to override this method on the skin class itself.
46
Life: DefermentDeferment is the core concept of the component lifecycle!Put off doing the “real work” until the appropriate timeValidation methods listen for the Prerender event - happen once before a render
Frame 1
set a component’s width - deferred
set width(deferred)
actuallyset width
rendercomponent
47
Life: Deferment
Queued InvalidationDeferred Validation
Render!
Player Events
UserCode
Prerender Event
User Code
Player Render
User Action Invalidate Action Render Action
InteractionAssign handlers to user events
Process things
Cause invalidation to occur
Away we go!
48
Invalidation
Validation
Interaction
Interaction: why?Events: objects passed around when anything interesting goes on (clicks, moves, changes, timers...)• If something happens to a component, it “fires” or “dispatches” the event• If another component wants to know when something happens, it “listens” for events
Event-based architecture is loosely-coupledEvent-based architectures are more reusableComponents don’t have to know anything about each other - just listen for the events!
49
Invalidation
Validation
Interaction
Interaction: how?Any component that inherits from EventDispatcher can send eventscomponent.dispatchEvent(event);Events are identified by a type (constant)Some popular events:• Event.CHANGE• MouseEvent.CLICK• FlexEvent.CREATION_COMPLETE• Event.RESIZE• MouseEvent.ROLL_OUT
50
Invalidation
Validation
Interaction
Interaction
51
Invalidation
Validation
Interaction
Capturing Phase
Target
Application Application
Bubbling Phase
Targeting Phase
Event propagation happens in 3 phases:1. Capturing2. Targeting3. Bubbling
event.target vs. event.currentTarget
52
target: the object that dispatched the event (doesn’t change)
currentTarget: the object who is currently being checked for specific event listeners (changes as we traverse the display tree during the capture or bubbling phase)
During the targeting phase, target == currentTarget.
Life Goes On
53
Interaction (dispatching events) sets the stage for the next user action
In the next user action we’ll process these events and set up more queued invalidation
In the invalidation action we’ll process all of that queued invalidation in our validation methods (commitProperties, updateElementsList, measure)
Render!
And so it goes, on and on forever, as long as your component remains on an elements list.
54
Death: Removal“Removal” refers to the process of removing a component from the elements list. These components can be re-parented (brought back to life) or abandoned to die
parent.removeElement(component);
Abandoned components don’t get validation calls and aren’t drawn. Ever.
If an abandoned component has no more active references, it *should* be garbage-collected
Re-parenting isn’t cheap, but it’s cheaper than re-creating the same component twice
Listen for FlexEvent.REMOVED from the component or ElementExistienceEvent.ELEMENT_REMOVED from the parent to do custom cleanup.
Consider hiding rather than removing (set visible and includeInLayout to false)
Removal
Garbage Collection
55
Death: Garbage CollectionAny object not on an element’s list with no active references is eligible for destruction, garbage collection
Use strongly typed objects
Use weak listeners
Be careful with object / dictionary references
The flash player does not reduce it’s footprint, though memory can be recycled
Removal
Garbage Collection
ConclusionRemember the frame model! It will help you understand what’s happening in your Flex application. For Flash developers this is second nature; for Java or .NET devs it’s an adjustment.
Queued Invalidation & Deferred Validation are the core concepts of the component lifecycle
Master the validation methods, and know which to override for any situation
56
More Reading / Bibliography
57
360 | Flex Talk with Brad Umbaugh on the Flex 3 Component Lifecyclehttp://tv.adobe.com/watch/360flex-conference/diving-deep-with-the-flex-component-lifecycleA video of our 360|Flex presentation on the Flex 3 lifecycle. It’s long and in depth.
Ely Greenfield: “Building a Flex Component” (Flex 3)http://onflex.org/ACDS/BuildingAFlexComponent.pdfA presentation Ely gave years ago that I still review.
Sean Christmann on the Elastic Racetrack / Frame modelhttp://www.craftymind.com/2008/04/18/updated-elastic-racetrack-for-flash-9-and-avm2/This blog post is the granddaddy of every discussion about the Flash frame model or component lifecycle.
Flex 4 Training by Development Archttp://www.developmentarc.comJames Polanco and Aaron Pedersen do affordable online Flex 4 training. Their one day session covers much of this material in more depth.
58
Thanks!
RJ [email protected]: @rjowen
www.effectiveui.com
Get these slides:http://www.slideshare.net/rjowenhttp://goo.gl/nrmX