Upload
bhbagadiya
View
221
Download
0
Embed Size (px)
Citation preview
8/8/2019 Diving Deep, Component Life Cycle
1/76
Diving Deep with the Flex
Component LifecycleJoshua Jamison
EffectiveUI
www.effectiveui.com
January 30, 2009
http://www.effectiveui.com/http://www.effectiveui.com/http://www.effectiveui.com/8/8/2019 Diving Deep, Component Life Cycle
2/76
Who am I?
Joshua Jamison
Software Architect @ EffectiveUI
8/8/2019 Diving Deep, Component Life Cycle
3/76
Who are you (hopefully)?
Beginner to intermediate level developers
Anyone who doesnt currently understand
the lifecycle
Anyone who wants a good review of the
basics
8/8/2019 Diving Deep, Component Life Cycle
4/76
Whats this about, anyway?
Flex component lifecycleFlex frame cycle (elastic racetrack)
8/8/2019 Diving Deep, Component Life Cycle
5/76
Flex Component Lifecycle
What is it? The way the framework interacts with
every Flex component
A set of methods the framework calls toinstantiate, control, and destroy
components
Methods that make the most of the
elastic racetrack
8/8/2019 Diving Deep, Component Life Cycle
6/76
Elastic Racetrack: introduction
Flex component lifecycle is built on this
frame model
image courtesy of Ted Patrick
8/8/2019 Diving Deep, Component Life Cycle
7/76
A frame in AS3
image courtesy of Sean Christmann
8/8/2019 Diving Deep, Component Life Cycle
8/76
Phases of the Lifecycle
3 Main Phases:
BIRTH:
construction, conguration,
attachment, initialization LIFE:
invalidation, validation, interaction
DEATH:
detachment, garbage collection
8/8/2019 Diving Deep, Component Life Cycle
9/76
BirthCongratulations: Youre about to have a component.
8/8/2019 Diving Deep, Component Life Cycle
10/76
Construction
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
11/76
What is a constructor?
A function called to instantiate (create in
memory) a new instance of a class
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
12/76
How is a constructor invoked?
Actionscript:
MXML:
vartheLabel : Label =newLabel();
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
13/76
What does a constructor have access to?
Properties on the classMethods on the class
Children have not yet been created!
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
14/76
What does an ActionScript3
constructor look like?
No required arguments (if it will be used inMXML); zero, or all optional
Only one per class (no overloading!)
No return type
Must be public
Calls super() to invoke superclass constructor; if
you dont, the compiler will!
publicfunctionComponentName()
{
super();
//blah blah blah
}
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
15/76
What does an MXML constructor
look like?
No need to dene one. In fact, if you tryto put one in an block, youll
get an error.
Why? Remember: MXML = Actionscript. Aconstructor is created by the compiler in
the Actionscript generated from the
MXML.
Specify -keep in the Flex Buildercompiler arguments and look at the
generated code to verify this.
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
16/76
What should a constructor do?
Not much. Since the componentschildren have not yet been created, theres
not much that can be done.
There are speci
c methods (such ascreateChildren) that should be used for
most of the things youd be tempted to
put in a constructor.
A good place to add event listeners to the
object.Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
17/76
Dont create or attach children in
the constructor
Its best to delay the cost of createChildrencalls for added children until its necessary
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
18/76
Conguration
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
19/76
Conguration
The process of assigning values toproperties on objects
In MXML, properties are assigned in this
phase, before components are attached or
initialized
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
20/76
Hooray: Sample code!
SampleChild constructorSampleChild.property1 setter
Adding child SampleChild4
...
Output:
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
21/76
Conguration and Containers
Containers must not expect their childrenhave to be instantiated when properties
are set.
SampleContainer constructor
SampleContainer.property1 setter
SampleChild constructor
SampleChild.property1 setter
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
22/76
Conguration Optimization
To avoid performance bottlenecks, make
your setters fast and defer any real work
until validation
Well talk more about deferment in the
validation / invalidation section
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
23/76
Attachment
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
24/76
What is attachment?
Adding a component to the display list
(addChild, addChildAt, MXML declaration)
The component lifecycle is stalled after
conguration until attachment occurs.
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
25/76
Consider this component:
publicclassAextendsUIComponent { publicfunctionA(){ trace("CONSTRUCTOR"); super(); } overrideprotectedfunctioncreateChildren():void{ trace("CREATECHILDREN"); super.createChildren(); } overrideprotectedfunctionmeasure():void{ trace("MEASURE"); super.measure(); } overrideprotectedfunctionupdateDisplayList(width:Number, height:Number):void{ trace("UPDATEDISPLAYLIST"); super.updateDisplayList(width,height); } overrideprotectedfunctioncommitProperties():void{ trace("COMMITPROPERTIES"); super.commitProperties(); }
(It traces all of its methods.)
8/8/2019 Diving Deep, Component Life Cycle
26/76
And this application:
Without attachment, the rest of the lifecycle
doesnt happen.
overrideprotectedfunctioncreateChildren():void{ super.createChildren(); vara:A=newA(); }
]]>
CONSTRUCTOROutput:
8/8/2019 Diving Deep, Component Life Cycle
27/76
But what about this application?
Moral of the story: dont add components to the
stage until you need them.
this.addChild( a ); } ]]> Output: CONSTRUCTOR
CREATECHILDREN
COMMITPROPERTIES
MEASURE
UPDATEDISPLAYLIST
8/8/2019 Diving Deep, Component Life Cycle
28/76
Initialization
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
29/76
Initialization
2 phases, 3 events:
1. preInitialize dispatched
2. createChildren(); called3. initialize dispatched
4. rst validation pass occurs
5. creationComplete dispatched
Create
Validate
Birth
construction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
30/76
createChildren()
MXML uses the createChildren() method to add
children to containers Override this method to add children using AS
Follow MXMLs creation strategy: create,
congure, attach
overrideprotectedfunctioncreateChildren():void
{
...
textField=newUITextField();
textField.enabled=enabled;
textField.ignorePadding=true;
textField.addEventListener("textFieldStyleChange",
textField_textFieldStyleChangeHandler);
...
...
addChild(DisplayObject(textField));
}
create
congure
attach
8/8/2019 Diving Deep, Component Life Cycle
31/76
rst validation pass
Invalidation is not part of initialization -only Validation
Validation consists of 3 methods:
commitProperties() measure()
updateDisplayList()
more on these laterBirthconstruction
conguration
attachment
initialization
LifeDeath
8/8/2019 Diving Deep, Component Life Cycle
32/76
LifeThey grow up so fast.
8/8/2019 Diving Deep, Component Life Cycle
33/76
Invalidation
Birth
Life
invalidation
validation
interactionDeath
8/8/2019 Diving Deep, Component Life Cycle
34/76
Invalidation / Validation cycle
Flex imposes deferred validation on the
Flash API
goal: defer screen updates until all
properties have been set
3 main method pairs to be aware of: invalidateProperties() ->
commitProperties()
invalidateSize() -> measure() invalidateDisplayList() ->
updateDisplayList()
8/8/2019 Diving Deep, Component Life Cycle
35/76
Invalidation / Validation theory
First, a little theory.
8/8/2019 Diving Deep, Component Life Cycle
36/76
Deferment
Deferment is the central concept to
understand in the component Life-cycle
Use private variables and boolean ags todefer setting any render-related
properties until the proper validation
method
8/8/2019 Diving Deep, Component Life Cycle
37/76
Text-book example
publicfunctionsettext(value:String):void
{
myLabel.text=value;
// Possible Error! during first config phase,
// myLabel might not exist!
}
privatevar_text:String="";
publicfunctionsettext(value:String):void
{
textSet=true;
_text=value; textChanged=true;
invalidateProperties();
invalidateSize();
invalidateDisplayList();
}
overrideprotectedfunction
commitProperties():void{
{
if(textChanged){myLabel.text=_text;
textChanged=false;
}
super.commitProperties();
}
Bad:
Good:
8/8/2019 Diving Deep, Component Life Cycle
38/76
The Elastic Racetrack revisited
Invalidation occurs here
image courtesy of Sean Christmann
8/8/2019 Diving Deep, Component Life Cycle
39/76
Invalidation methods
invalidateProperties() Any property changes
invalidateSize()
Changes to width or height
invalidateDisplayList()
Changes to child component size or
positionBirth
Life
invalidation
validation
interactionDeath
8/8/2019 Diving Deep, Component Life Cycle
40/76
Invalidation example 1
8/8/2019 Diving Deep, Component Life Cycle
41/76
Invalidation example 2publicclassBadListextendsVBox { privatevar_dataProvider:ArrayCollection;
publicfunctionsetdataProvider(arr:ArrayCollection):void{ this._dataProvider=arr; arr.addEventListener(CollectionEvent.COLLECTION_CHANGE,dataProviderChangeHandler); } privatefunctiondataProviderChangeHandler(e:Event):void{
this.removeAllChildren(); foreach(varn:Numberinthis._dataProvider){ varl:Label=newLabel(); l.text=n.toString(); this.addChild(l); }
} publicfunctionBadList(){} }Result: dataProviderChangeHandler called 20 times
8/8/2019 Diving Deep, Component Life Cycle
42/76
Invalidation example 3publicclassGoodListextendsVBox { privatevar_dataProvider:ArrayCollection; privatevar_dataProviderChanged:Boolean=false;
publicfunctionsetdataProvider(arr:ArrayCollection):void{ this._dataProvider=arr; arr.addEventListener(CollectionEvent.COLLECTION_CHANGE,dataProviderChangeHandler); this._dataProviderChanged=true; this.invalidateProperties(); } overrideprotectedfunctioncommitProperties():void{
super.commitProperties(); if(this._dataProviderChanged){ this.removeAllChildren(); foreach(varn:Numberinthis._dataProvider){ varl:Label=newLabel(); l.text=n.toString(); this.addChild(l); } this._dataProviderChanged=false; } } privatefunctiondataProviderChangeHandler(e:Event):void{ this._dataProviderChanged=true; this.invalidateProperties(); } publicfunctionGoodList(){} }
Result: commitProperties
called only twice (once
during initialization)
8/8/2019 Diving Deep, Component Life Cycle
43/76
Validation
Birth
Life
invalidation
validation
interactionDeath
8/8/2019 Diving Deep, Component Life Cycle
44/76
The Elastic Racetrack revisited
Validation occurs here
8/8/2019 Diving Deep, Component Life Cycle
45/76
Validation
Apply the changes deferred duringinvalidation
Update all visual aspects of the
application in preparation for the render
phase
3 methods:
commitProperties()
measure()
updateDisplayList()Birth
Life
invalidation
validation
interactionDeath
8/8/2019 Diving Deep, Component Life Cycle
46/76
commitProperties()
Ely says: Calculate and commit the effects
of changes to properties and underlying
data. Invoked rst - immediately before
measurement and layout
Birth
Life
invalidation
validation
interactionDeath
8/8/2019 Diving Deep, Component Life Cycle
47/76
commitProperties() cont.
ALL changes based on property and data
events go here
Even creating and destroying children, so
long as theyre based on changes toproperties or underlying data
Example: any list based component with
empty renderers on the screenBirth
Life
invalidation
validation
interactionDeath
8/8/2019 Diving Deep, Component Life Cycle
48/76
measure()
Component calculates its preferred(default) and minimum proportions
based on content, layout rules,
constraints.
Measure is called bottom up - lowest
children rst
Caused by invalidateSize()
NEVER called for explicitly sized
componentsBirth
Life
invalidation
validation
interactionDeath
idi ()
8/8/2019 Diving Deep, Component Life Cycle
49/76
overriding measure()
Used for dynamic layout containers (VBox,etc.)
Use getExplicitOrMeasuredWidth() (or
height) to get child proportionsALWAYS called during initialization
Call super.measure() rst!
Set measuredHeight, measuredWidth forthe default values; measuredMinHeight
and measuredMinWidth for the minimum.Birth
Life
invalidation
validation
interactionDeath
()
8/8/2019 Diving Deep, Component Life Cycle
50/76
measure() cont.
Not reliable - Framework optimizes awayany calls to measure it deems
unecessary
Birth
Life
invalidation
validation
interaction
Death
d Di l Li ()
8/8/2019 Diving Deep, Component Life Cycle
51/76
updateDisplayList()
All drawing and layout code goes here,making this the core method for all
container objects
Caused by invalidateDisplayList();Concerned with repositioning and
resizing children
updateDisplayList() is called top-downBirth
Life
invalidation
validation
interaction
Death
O idi d Di l Li ()
8/8/2019 Diving Deep, Component Life Cycle
52/76
Overriding updateDisplayList()
Usually call super.updateDisplayList() rst
super() is optional - dont call it if youre
overriding everything it does
Size and lay out children using move(x,y)and setActualSize(w,h) if possible
I never have good luck with
setActualSize()Birth
Life
invalidation
validation
interaction
Death
El ti R t k t
8/8/2019 Diving Deep, Component Life Cycle
53/76
Elastic Racetrack cont.
User Actions Dispatch invalidation events
Interact with any non-validation events
from this frame (mouse movements,timers, etc.)
El ti R t k C t
8/8/2019 Diving Deep, Component Life Cycle
54/76
Elastic Racetrack Cont.
Invalidate Action Process all validation calls
Render Action
Do the heavy lifting - actually draw onthe screen
Th El ti R t k i it d
8/8/2019 Diving Deep, Component Life Cycle
55/76
The Elastic Racetrack revisited
Queued Invalidation
Deferred ValidationRender!
8/8/2019 Diving Deep, Component Life Cycle
56/76
Interaction
Birth
Life
invalidation
validation
interaction
Death
How do objects know when
8/8/2019 Diving Deep, Component Life Cycle
57/76
How do objects know when
something happens?
Events: objects passed around whenanything interesting goes on (clicks,
moves, changes, timers...)
If something happens to a component, itres or dispatches the event
If another component wants to know
when something happens, it listens for
events
Event-based architecture is loosely-
coupled
Birth
Life
invalidation
validation
interaction
Death
Benets of Loosely-Coupled
8/8/2019 Diving Deep, Component Life Cycle
58/76
Benets of Loosely Coupled
Architectures
Everything becomes more reusable
Components dont have to know anythingabout the components in which theyre
used
Birth
Life
invalidation
validation
interaction
Death
Who can dispatch e ents?
8/8/2019 Diving Deep, Component Life Cycle
59/76
Who can dispatch events?
Subclasses of EventDispatcher
EventDispatcher inherits directly from
ObjectSimply call dispatchEvent(event) to re off
an event when something happens
Birth
Life
invalidation
validation
interaction
Death
How to tell events apart?
8/8/2019 Diving Deep, Component Life Cycle
60/76
How to tell events apart?
Event class
Different classes allow for customized
payloads
typeeld: a constant
Birth
Life
invalidation
validation
interaction
Death
Common Events
8/8/2019 Diving Deep, Component Life Cycle
61/76
Common Events
Event.CHANGE
MouseEvent.CLICK
FlexEvent.CREATION_COMPLETEEvent.RESIZE
MouseEvent.ROLL_OUT
Birth
Life
invalidation
validation
interaction
Death
Handling Events
8/8/2019 Diving Deep, Component Life Cycle
62/76
Handling Events
theButton.addEventListener( MouseEvent
.CLICK, callThisFunction )
Birth
Life
invalidation
validation
interaction
Death
Event Propagation
8/8/2019 Diving Deep, Component Life Cycle
63/76
Event Propagation
CapturingPhase
Target
Application Application
BubblingPhase
TargetingPhase
Three phases: Capturing, Targeting, Bubbling
Birth
Life
invalidation
validation
interaction
Death
8/8/2019 Diving Deep, Component Life Cycle
64/76
Event Propagation Three phases: Capturing, Targeting, Bubbling
button.addEventListener(MouseEvent.CLICK,clickHandler,false); } publicfunctionclickHandler(e:Event):void{ trace("----------------------------------------------------------"); trace("TARGET: "+e.target.id); trace("CURRENT TARGET: "+e.currentTarget.id); trace("PHASE: "+(e.eventPhase==1 ?"CAPTURE":(e.eventPhase==2?"TARGET":"BUBBLE"))); } ]]>
Birth
Life
invalidation
validation
interaction
Death
8/8/2019 Diving Deep, Component Life Cycle
65/76
Event Propagation----------------------------------------------------------
TARGET: button
CURRENT TARGET: eventTest
PHASE: CAPTURE----------------------------------------------------------
TARGET: buttonCURRENT TARGET: outer
PHASE: CAPTURE
----------------------------------------------------------
TARGET: buttonCURRENT TARGET: inner
PHASE: CAPTURE----------------------------------------------------------
TARGET: button
CURRENT TARGET: button
PHASE: TARGET----------------------------------------------------------
TARGET: buttonCURRENT TARGET: inner
PHASE: BUBBLE
----------------------------------------------------------
TARGET: button
CURRENT TARGET: outerPHASE: BUBBLE----------------------------------------------------------
TARGET: buttonCURRENT TARGET: eventTest
PHASE: BUBBLE
Birth
Life
invalidation
validation
interaction
Death
Stopping events from propagating
8/8/2019 Diving Deep, Component Life Cycle
66/76
Stopping events from propagating
stopPropagation() : Prevents processingof any event listeners in nodes
subsequent to the current node in the
event ow
stopImmediatePropagation() : Prevents
processing of any event listeners in the
current node and any subsequent nodes
in the event owBirth
Life
invalidation
validation
interaction
Death
target vs currentTarget
8/8/2019 Diving Deep, Component Life Cycle
67/76
target vs. currentTarget
target: the object that dispatched the
event (doesnt change)
currentTarget: the object who is currentlybeing checked for specic event listeners
(changes)
Birth
Life
invalidation
validation
interaction
Death
Dispatching events from custom
8/8/2019 Diving Deep, Component Life Cycle
68/76
Dispatching events from custom
components
MXML:
Actionscript:
[Event(name="atePizza", type="flash.events.JoshEvent")]
[Event(name="atePizza", type="flash.events.JoshEvent")]
public class MyComponent extends UIComponent
{
...
}
Birth
Life
invalidation
validation
interaction
Death
8/8/2019 Diving Deep, Component Life Cycle
69/76
DeathAll good things come to an end.
8/8/2019 Diving Deep, Component Life Cycle
70/76
Detachment
Birth
Life
Death
detachment
garbage
collection
Detachment
8/8/2019 Diving Deep, Component Life Cycle
71/76
Detachment
Detachment refers to the process ofremoving a child from the display list
These children can be re-parented
(brought back to life) or abandoned to dieAbandoned components dont get
validation calls and arent drawn
If an abandoned component has no moreactive references, it *should* be garbage-
collectedBirth
Life
Death
detachment
garbage
collection
Detachment cont
8/8/2019 Diving Deep, Component Life Cycle
72/76
Detachment cont.
Re-parenting isnt cheap, but its cheaperthan re-creating the same component
twice
Children do not need to be removed from
their parent before being re-parented, butalways should be
Consider hiding rather than removing
set visible and includeInLayout to falseBirth
Life
Death
detachment
garbage
collection
8/8/2019 Diving Deep, Component Life Cycle
73/76
Garbage Collection
Birth
Life
Death
detachment
garbage
collection
Garbage Collection
8/8/2019 Diving Deep, Component Life Cycle
74/76
Garbage Collection
The process by which memory is returned
to the system
Only objects with no remaining references
to them will be gcd Set references to detached children to
null to mark them for GC
Talk to Grant Skinner about forcing GC http://gskinner.com/blog/archives/2006/08/as3_resource_ma_2.htmlBirth
Life
Death
detachment
garbage
collection
Conclusion
http://gskinner.com/blog/archives/2006/08/as3_resource_ma_2.htmlhttp://gskinner.com/blog/archives/2006/08/as3_resource_ma_2.html8/8/2019 Diving Deep, Component Life Cycle
75/76
Conclusion
Defer, Defer, DEFER!
Use validation methods correctlyRemember the elastic racetrack
References
8/8/2019 Diving Deep, Component Life Cycle
76/76
References
Ely Greeneld: Building a Flex Component
http://www.onex.org/ACDS/BuildingAFlexComponent.pdf
Chac Kazoun, Joey Lott: Programming Flex 2 by
OReilly http://oreilly.com/catalog/9780596526894/
Colin Moock: Essential Actionscript 3.0 by OReilly
http://oreilly.com/catalog/9780596526948/
index.html
http://oreilly.com/catalog/9780596526948/index.htmlhttp://oreilly.com/catalog/9780596526948/index.htmlhttp://oreilly.com/catalog/9780596526948/index.htmlhttp://oreilly.com/catalog/9780596526948/index.htmlhttp://oreilly.com/catalog/9780596526894/http://oreilly.com/catalog/9780596526894/http://www.onflex.org/ACDS/BuildingAFlexComponent.pdfhttp://www.onflex.org/ACDS/BuildingAFlexComponent.pdfhttp://www.onflex.org/ACDS/BuildingAFlexComponent.pdfhttp://www.onflex.org/ACDS/BuildingAFlexComponent.pdf