Application development

with JavaScript, Flex, and AIR

Primer on the Flex 3 Component Lifecycle

Abstract: The Flex component lifecycle
is a Flex framework mechanism for optimizing and coordinating the processes
that create, update, and destroy Flex components. This primer provides an
overview of the lifecycle and describes how you can leverage it to create
more advanced and efficient components.

Scope: This is written for Flex 3,
not Flex 4. The Flex 4 lifecycle is briefly covered in the Conclusion section.

Audience: This primer assumes you’re
familiar with OOP basics. It also assumes you know how to employ these principles
in Flex. So, not only should you understand class hierarchies and inheritance
in a general sense, you should also know how to create a Flex class that extends
a framework class, how to override a parent method to modify/add behavior,
etc.

Flex Component Lifecycle - Overview

The Flex component lifecycle is a Flex framework mechanism for managing and
optimizing the processes that control all components. These processes perform
tasks required by components (e.g., the creation of a composite component’s
children) in a consistent sequence (e.g., children are created before attempting
to modify their properties).

The term components is used here for the
visual classes that you add to the display list and which comprise your UI.
You can also create non-visual classes – for example, data structures to serve
as value objects – but these don’t participate in the component lifecycle
and aren’t covered here.

The processes of the lifecycle are surfaced to you, the Flex
developer, as protected methods.
When creating your components you can override these lifecycle methods to
perform tasks such as sizing and positioning child components. Understanding
how the component lifecycle works can help you to perform these tasks more
efficiently and thus allow you to create more efficient components.

Lifecycle methods are implemented in the UIComponent class. UIComponent
is also the base class for all Flex components. As a result, all Flex components
inherit the lifecycle methods and participate in the component lifecycle (but
Flash-based components like MovieClip don’t inherit from UIComponent and as
a result don’t participate in the lifecycle).

The Flex component lifecycle is divided into three primary phases.

Initialization (birth phase)

Update (life phase)

Destruction (death phase)

These primary phases are further divided into steps, or subprocesses.
We’ll look at these in a moment, but to get a feel
for what the lifecycle does let’s start by considering just one task your
component will require, the rendering of property changes to the screen.

Like many things in Flex, render operations are performed asynchronously
– when your component instructs Flex to change it’s border from blue to yellow
the operations that render that border color aren’t executed immediately.
That’s one of the optimization features of the Flash player and the component
lifecycle – render requests are deferred so they can be applied efficiently.

How can deferral increase efficiency? Consider the case where your code
changes your component’s border to yellow to indicate a warning condition
but then encounters an error and sets the border to red to indicate an error
condition. If property rendering was performed immediately and the component’s
border was initially blue you’d see the border flashing from blue to yellow
to red. More importantly, the rendering processing would execute twice when
once was all you needed – you really only need that final value (red) displayed.
In this case it’s more efficient to defer screen updates until you have your
final property value (final for this frame’s execution). The final property
value “wins”, only that value is rendered.

The above may seem a trivial inefficiency, but consider scaling it up over
many complex components undergoing many visual property changes which trigger
many redundant render operations. Do this and you’ll soon start seeing unpleasant
side effects.

Keep in mind that rendering can be very expensive when a property change
results in Flex having to adjust the layout and redraw many (or potentially
all) objects currently on the display tree. A property assignment that can
execute in a millisecond can take much longer to render to the screen. For
example, it takes only an instant to increase a child component’s font size
with a setStyle call but this small change can result in significant render
processing.

So, efficient handling of property changes that require rendering to the
screen is important. Optimizing how your properties are processed and
ultimately rendered is one benefit of the Flex component lifecycle.
As we’ll see, there are many others.

Before we talk more about the component lifecycle we need a small digression
to consider how frames are handled in the Flash Player’s ActionScript
virtual machine, or AVM.

The Flash player and frame processing

Your Flex app runs in the Flash player, which provides the virtual machine
within which your ActionScript code executes (note that AS3 uses the Flash
player’s second-generation virtual machine, AVM2). The Flash player uses
single-threaded execution, processing code sequentially, and it does its
processing in cycles, breaking work up into units of work called frames.
The frame processing frequency is controlled by the SWF’s frame rate. By
default Flex will execute (or attempt to execute) 24 frames per second (FPS).

At its most basic, each frame consists of a code execution phase followed
by a render phase as illustrated below.

Figure 1: Basic frame composition

The frame’s code execution phase is where:

your own ActionScript code executes. Examples of this include
performing mathematical calculations, an event handler running in response
to a user click event, populating an ArrayCollection in response to a HTTPService
ResultEvent.

The frame’s rendering phase is where properties are translated to pixels.
If your component is cached as a bitmap then rendering can be
cheap in terms of processing, but when it needs to be redrawn from its properties
things can get expensive. Especially when the display tree is deep.

Some examples of rendering:

resizing a component on the screen in response to a browser resize

removing a component from the screen when you’ve set its visible
property to false

updating the bars of a bar chart when its dataProvider changes

Understanding the cyclical nature of frame processing and the Flash player’s
(and therefore Flex’s) linear, asynchronous processing model can help you
optimize your components. Alternatively, improperly integrating your component
into the lifecycle can result in screen flicker, draggable windows that move
jerkily, and generally suboptimal performance and memory utilization.

We’ll look at the Flash player and frame processing again a bit later, but
now let’s return to the component lifecycle and its processes.

LifeCycle Phases

The lifecycle is divided into three primary phases as shown in the table below.
Note that the term lifecycle is appropriate and descriptive here – we’re talking
about the creation of your component (its birth) and its ongoing participation
in your application (its life) and its ultimate removal from your application
(its death).

Lifecycle Phase

What the phase does for your component

Initialization (Birth)

memory is allocated to your
component, its properties are assigned values, it’s added to the display
list, if it has children they are created and layed out, etc.

Not surprisingly, the Initialization phase is the most complex of the 3 phases.
Let’s drill into it and see how your component is created, configured, and
ultimately rendered to the screen.

Lifecycle Phase 1 - Initialization

The Initialization phase consists of many processes that create your component
and eventually cause it to appear on the stage. Most of these processes are
triggered by and dependant upon the completion of a predecessor process.
It’s the Flex component lifecycle that ensures
all of these processes execute in the proper order and with a consistent set
of triggers.

Consider what needs to happen when your component is created:

on the creation call (e.g., new myComponent();) Flex first has
to perform low-level setup tasks like memory allocation

once the class instance exists in memory it can be assigned
property values, things like color=“#FFFFFF”, visible=false, etc. These
properties can come from several places, including Flex default property values,
property values specified in MXML tags or assigned in ActionScript code,
and of course Flex takes into account attributes set through CSS

only after general properties are known can your component be
measured (though this step isn’t required if you’ve provided explicit sizes).
For example, you can’t determine a text field’s height and width until you
know its font size.

once height and width are known Flex can determine dependant
information such as the size of your component’s parent container (required
if the parent doesn’t have a fixed size, e.g. a VBox with no height/width
specified) and where the component belongs on the screen (its x/y coordinates)

only after all of the above have been completed, at the end
of the initialization phase, can Flex render your component to the screen

The rest of this section (and the majority of this article) will focus on Initialization processes.

1.1 Construction

The first step in component creation is execution of its constructor. Your
constructor could be triggered through:

·execution of ActionScript (e.g., new myComponent(); )

- OR -

·an MXML instantiation (e.g.,
&nbsp<myComps:myComponent/> )

In general your component’s constructor should do minimal work. It’s ok
to define event handlers here and you can set default values for properties
inherited from the parent class. However, in general your constructor should
not create children or assign property values on child components –
for these tasks you’ll use the lifecycle methods createChildren and commitProperties
(we'll cover these in a moment).

Note that construction is one place where MXML and AS components differ:

MXML components do not contain a constructor (don’t try to create
a constructor in a <mx:Script> block of your MXML component, you’ll
get a compile error)

If you want to use the component in MXML then your constructor
must have no required arguments, since MXML provides no way to pass values
to a component constructor

Reminder: This
doesn’t cover details on some topics
like constructors. However, resources listed at the end of this article
provide in-depth information on all topics covered in this article.

1.2 Configuration

Configuration is where the Flex framework processes your component’s property
values. This includes default property values, property values set in the
constructor, and property values set by the user of your component (but not
style properties, including inherited CSS, these are processed only after
your component has been added to the display list).

Examples of setting component properties:

mycompInstance.msgText = “some text” ;

- OR –

<myComps:MyComponent id=“mycompInstance” msgText=“some text”/>

Your component will often create new properties that you can expose through
either public variables or through a setter method. So, either:

Both of the above will work, allowing the user of your component to set the
string “some text” on your component’s property msgText. However, it's strongly
recommended that you use setters rather than public variables.

One reason for using setters is that setters let you run code each time a
value is assigned to the property. This is especially important when your
component is a composite component – i.e., it contains other components, or
children. Why? Because at component configuration time your child components
don’t yet exist (they’re created later, in the createChildren method).

To handle property assignments on child components the convention is to use
a setter to store the property value in a private variable and then – after
you’re sure your child component has been created – you’ll assign this stored
value to the child’s property. We’ll cover this later when we consider the
lifecycle method commitProperties. For now, just note that the processing
of your component’s property values occurs immediately after construction.

Of course, another reason for using a setter rather than a public variable
is that it’s just good OOP – objects external to your component shouldn’t
be allowed to directly access your component’s internal data (the principle
of encapsulation).

1.3 Attachment

The next step in the Initialization phase is adding your component to the
display list. When you instantiate your component through MXML this
attachment occurs automatically.
When you instantiate the component through ActionScript you'll programmatically
add it to the display list using an addChild() or addChildAt() call. So, something like:

It’s worth noting that the bulk of your component's initialization processing occurs only
after the component has been added to the display list; if you don’t add your
component to the display list the component lifecycle processing will stall.

Components aren’t immediately visible upon a call to addChild(). Rather,
attachment makes your component able to participate in the remainder of the
component lifecycle, particularly the invalidation/validation processing where
critical tasks like measuring and layout are performed.

It’s in the Attachment step, after your component has been added to the display
list, that CSS style properties are processed. Style values can be set earlier,
even in the constructor, but they aren’t actually processed (including walking
the styles tree to determine inherited styles) and applied to your component
until it’s on the stage.

Now that our component has been created and added to the display list the
initialization step of the lifecycle’s Initialization phase can kick off.

1.4 Initialization

The initialization step of the lifecycle's Initialization phase is where the bulk of
your component creation work occurs. It’s also the first time your component
participates in the lifecycle’s invalidation/validation processing, which
is used throughout the component lifecycle (i.e., not just during your component’s
“birth”, but also during its “life”)

A summary of the Initialization subprocesses and their execution order is below:

1. Initialization

1.1 construction

1.2 configuration

1.3 attachment

1.4 initialization

1.4.1 dispatch preInitialization event

1.4.2 createChildren() is called

1.4.3 dispatch initialization event

1.4.4 first full invalidation/validation pass

1.4.5 dispatch creationComplete event

2. Update

3. Destruction

While steps 1.4.2 and 1.4.4 are the focus of the remainder of this section,
it’s worth taking a moment to consider the environment that exists when the
events listed above fire.

when the preInitialization event fires your component’s
children haven’t yet been created. So, if your component creates subcomponents
(children) you should be careful when overriding preInitialization – here,
don’t include code that references children you'll be creating in createChildren
else you’ll get a null reference RTE.

upon dispatch of the initialization event your component’s
children exist, but (as we’ll see in a moment) your component is not quite
ready for prime time – some properties have not yet been determined, most
notably its size and width (unless an explicit size and width were assigned)
and its x/y coordinates.

By the time the creationComplete event fires your component
has been configured, measured and layed out. It’s now visible on the screen,
ready for use.

1.4.2 createChildren()

The createChildren method is where you create your component’s child components.
For example, if you’re creating a composite component that consists of several
text fields, a checkbox, and a button you would create each of these here.

Some examples of Flex composite components are:

the Button class, which extends UIComponent and has one child,
a UITextField for the label text

ComboBox, which also extends UIComponent and contains a TextInput
control to display the text and a Button control for the selection arrow

the RichTextEditor, which is a very complex composite, contains
many other components

When creating children you follow the create/configure/attach pattern. This
is reflected in the child creation sample code below:

Note the initial check to see if messageField already exists. This is standard
practice when creating component children. Why might a child already exist?
Because your custom component, which is a subclass of some other component,
might itself be subclassed. In that case the subclass might have already
created the messageField child in order to add/modify properties or behavior.

In createChildren you can for the first time safely set properties on
child components (because at this point you can be sure they exist). As mentioned
earlier, assigning values to properties of your component's child components through
setters requires special
processing, since setters can fire at component creation time (in the Configuration
step) when the child doesn’t yet exist. We’ll cover this special processing
in-depth when we look at the commitProperties method.

Finally, be aware that creating your component’s children within createChildren
is a general rule. Child components that aren’t required throughout the entire
lifecycle of your component – i.e., children that are dynamic, added and/or
removed during your component’s life – or children that depend on data created
later in the initialization process should be created within the commitProperties
method. Why? Because createChildren is executed only once in the life of
your component – at creation time, or “birth”. The commitProperties method
runs at creation time, too, but it also executes during the life of your component.
In fact there are several lifecycle methods that execute in both the Initialization
and Update (birth and life) phases. These methods belong to the Flex framework
invalidation/validation pattern, and that’s the next topic we’ll cover.

1.4.4 first full invalidation/validation pass

After executing the createChildren method Flex invokes a series of methods
based on an invalidation/validation pattern. This portion of the lifecycle
is designed to handle changes to component properties, determine the height
and width of your component, and determine where to position it (and its children)
on the screen. It’s a big topic and applies to the Update phase as well as
the Initialization phase so it’s covered in a separate section.

The Invalidation/Validation Model

As with other aspects of the component lifecycle, the invalidation/validation
model is used to sequence processes and increase efficiency by deferring work.
Your use of this lifecycle feature will in part depend on the component you’re
creating. If you’re creating a one-off component that has no children and
is tightly bound to your application then you might not make use of the lifecycle’s
validation methods. In this case efficiency might not be at a premium. However,
if you’re creating a component that will be used often (e.g., a tool for a
library shared with other Flex developers) then you should leverage this lifecycle
feature. Understanding this portion of the lifecycle is one of the most important
factors in writing efficient components.

It’s worth mentioning that the invalidation/validation model is used by nearly
all Flex framework components. Adobe developers did this because framework
components need maximum efficiency. You can learn a lot by looking at Flex
source code and see how they exploit the invalidation/validation model (for
example, see the source for the Panel class).

Validation methods

Validation methods are used to:

set and update your component’s properties

determine your component’s measurements (height and width)

perform layout of child components

execute drawing operations on your component

The validation methods are summarized below. It’s important to note that
these methods execute in the order they’re listed – nearly all property values
are known before your component is measured, and its size must be known before
its children can be sized and positioned.

1. Initialization

1.1 construction

1.2 configuration

1.3 attachment

1.4 initialization

1.4.1 dispatch preInitialization event

1.4.2 createChildren() is called

1.4.3 dispatch initialization event

1.4.4 invalidation/validation

1.4.4.1 invalidation check

1.4.4.2 execution of validation methods

1.4.4.2.1 commitProperties()

1.4.4.2.2 measure()

1.4.4.2.3 updateDisplayList()

1.4.5 dispatch creationComplete event

2. Update

3. Destruction

Lifecycle Method

Purpose

commitProperties()

use to assign properties
to child components, assign properties that are dependant on other
properties, and sometimes to create children

measure()

use to calculate your component’s
height and width

updateDisplayList()

for drawing on your component
(e.g., bgColor) and (for composite components) for sizing/positioning
children

Table 2:Validation methods

A fourth validation method, layoutChrome, has been omitted
from this primer to keep this lifecycle intro a bit simpler.

In your custom components you’ll make use of validation methods by overriding
them to inject your own code into the lifecycle’s processing. For example,
when you create a composite component you’ll override updateDisplayList, and
that override will contain your code for sizing and positioning child components.

Note that you don’t need to override all (or any) of the lifecycle’s validation
methods in your component’s implementation; you override only those methods
that provide the functionality you need. For example, if you want to create
a container component that uses a custom layout (e.g., a reverse VBox that
lays out its children from bottom-to-top instead of top-to-bottom) you’d only
need to override updateDisplayList.

In the lifecycle’s Initialization phase all validation methods execute automatically.
However, in the lifecycle’s Update phase these methods are triggered by calling
an invalidation method. You will call these invalidation methods in your
own code or they can be (and often are) called by Flex framework code.

Invalidation methods

You can trigger a validation method by executing its associated invalidation
method (see table 3 below). Executing an invalidation method sets a Flex
framework flag that tells Flex you want its associated validation method executed.
During each frame
cycle, just prior to the frame's rendering phase, Flex checks these flags in the
invalidation pass (step 1.4.4.1).
If a flag has been set then its method is executed in the next validation pass
(step 1.4.4.2).

The component lifecycle invalidation methods are:

Flag method

Result

invalidateProperties()

sets a framework flag that will trigger execution of commitProperties()

invalidateSize()

sets a framework flag that will trigger execution of measure()

invalidateDisplayList()

sets a framework flag that will trigger execution of updateDisplayList()

Table 3: Invalidation methods

You might wonder why flags are used as opposed to directly calling the validation
methods. If you did that your setter that might look something like this:

This setter would probably give you the result you want - the property value
would change, and whatever code you’ve put in commitProperties would run.
And run right away. But in this case immediate execution isn’t a good thing.
In fact there are several problems with directly calling validation methods
(but we’ll consider only two).

First problem: with the setter above, if you changed msgText’s value several
times in a frame cycle you’d execute commitProps once for each property change.
But wouldn’t it be better to have it run only once, only after you have the
property’s final value?

Second problem: if you use this logic in 10 different setters and all 10
of these setters fire in a frame cycle then you’d execute commitProperties
10 times. But wouldn’t it be better to run it just once and have it process
everything in that single execution?

This should sound familiar. Remember our earlier example where we changed
a component’s borderColor from blue to yellow to red? In that example we learned that
Flex optimizes its
rendering through deferral. Well, the rationale for the lifecycle’s invalidation
flags is similar. In fact the lifecycle’s invalidation/validation mechanism
is one way Flex integrates into the Flash Player’s deferred rendering model.
Bottom line, the
invalidation/validation process is largely about timing and deferral – doing things at
the right time in the right order and doing them in as few executions as possible.

Of course, as a good programmer you wouldn’t write multiple setters like the one
above, you’d write more efficient code, maybe using flags to consolidate
calls to commitProperties. But why bother – that’s precisely what the Flex
framework has provided you with its component lifecycle methods.

To summarize: the lifecycle uses invalidation/validation to defer work and
increase efficiency. If you set hundreds of properties during a frame’s code
execution cycle you can ensure that commitProperties will execute in this frame cycle
– and execute only once – through a simple call to invalidateProperties.

So, where should you use invalidation methods? Calls to invalidation
methods are generally made in your setters. In the next section we’ll look
at a setter written to exploit the component lifecycle.

1.4.4.1 commitProperties()

The purpose of the commitProperties method is to:

efficiently/safely set property values

set property values that are dependant on other property values

create children which are dynamic or which depend on properties (especially
data) that isn’t available when the createChildren lifecycle method executes

commitProperties: efficiently/safely set values

In addressing the setting of property values let’s consider the case of a
composite component. The user of your component
will generally set component property values. Often these values will
affect your component’s children. For example, your component might surface
a text property whose value it displays in a child (say, a Text component).
If you named this property msgText
then the property-setting MXML code might look something like:

<myComps:MyCompositeComponent msgText=“some text”/>

But setting this property on a child component presents a timing problem.
Remember step 1.2, the Configuration step? That’s where property values
are processed, and where setters execute (of course, setters can also execute
later in the life of your component, during the Update phase). But
the Configuration step can’t safely assign property values on your
children since they haven’t been created yet - you'll be creating them later,
in createChildren (step 1.3). When dealing with properties that will be applied
to child components you need to keep in mind timing - if you try to assign the string
“some text” to a child's text property before that child exists then bad things will happen
(i.e., you’ll get an RTE on a null object reference). The solution is commitProperties.
In commitProperties you can safely make the assignment
since the component lifecycle always executes commitProperties after createChildren.

By convention the assignment of values to child component properties is done
as follows:

1. the setter stores the property value in a holding variable
2. in commitProperties that value is committed

Let's look at this in more detail. Here’s some code that shows
how setters and commitProperties are used to safely set properties on
child components (explanation follows the code):

1. Your component defines a setter for its msgText property and some variables
this setter uses:

1.a. To surface the msgText property your component defines a setter. It
also defines a holding variable (in this context called backing store variable,
or just a backing variable) and a Boolean to use as a dirty flag.

1.b. The setter, which executes whenever a value is assigned to the property,
does the following:

first checks to see if the new value equals the current value,
and if true then does nothing (avoids unnecessary processing)

stores the new value in the backing store variable. By convention
the backing store uses a name in the format: underscore + name of the property
(so for the msgText
property it’s _msgText).

sets a flag to indicate this property value is now “dirty” and
needs to be processed (more on this below)

calls invalidation flags to trigger validation methods

2. In commitProperties:

the dirty flag is reset to false

the backing store value is assigned to the child component’s
text property

It’s important to note the dirty flag reset in step 2. Without that you’ll
have introduced inefficiency into your program, since without this flag reset
the msgText processing block would be triggered each time commitProperties
executes.

Also, in the above code all three invalidation methods are called. InvalidateProperties
is called to ensure that commitProperties executes, since that’s where you
actually commit the property value (hence the name). InvalidateSize is called
because changing the string may change the size (if no explicit size was given).
And invalidateDisplayList is called because a changed size may affect the
layout of your component’s children. Of course, you won’t always have to
call all three invalidation methods – for example, if the change is only to
the alignment within a text field you don’t need to measure or layout.

commitProperties: set values which are dependant on other values

In commitProperties you also assign values that are dependant on other properties.

About two years ago Peter Ent wrote a series of articles on creating custom classes,
and they include such a clear and concise explanation of this I'll just quote him here:

CommitProperties allows you “to set values which depend on the values of properties already
set. For example, suppose you have three properties: quantity, price, and
total. Where total = quantity*price. When do you set total? You can't set
in from the price setter because you don't know if quantity has been set.
You can't set it from quantity's setter because price might not be set. That's
where commitProperties comes it. When commitProperties is called you know
that all of your setter functions have been run. Now you can make the calculation
for total safely.”

commitProperties: create children

You can also use commitProperties to create children that are dynamic – i.e.,
aren’t needed through the entire life of your component and so are added/removed
dynamically. CreateChildren isn’t the place to do this since it executes
only once, during the lifecycle Initialization phase. However, commitProperties
executes during both the Initialization and Updates phases, which makes it
a good place for creating dynamic children.

You can also use commitProperties to create children that depend on properties
that aren’t available when the createChildren method executes. An example
of this might be a DataGrid whose data isn’t yet generated or retrieved when
createChildren executes.

Next up is a relatively simple validation method (and one you might not often
use), the measure method.

1.4.4.2 measure()

The purpose of the measure method is to determine the preferred size
of your component. This method assigns your component’s values for measuredHeight,
measuredWidth, measuredMinHeight, and measuredMinWidth.

It’s important to note that the sizes you set in measure aren’t necessarily
used in the final layout. They are your request to the framework, the sizes
you’d prefer. However, the final height and width may be adjusted by Flex
depending on available space and other factors.

In overriding measure you can omit a call to super.measure() if you
set all four height and width values. However, it’s a good practice to always
call super on a method. If you do call super then do it at the start of the
method, else the super call will overwrite the values you’ve set.

A warning is in order here: be careful what you put in measure since you
can’t rely on its execution even if you call invalidateSize. Why? Because
a component's height and width can be determined by explicit values as well
as measured values. For example there is a width-related property explicitWidth
as well as percentWidth and measuredWidth. When an explicit value is provided
then measure won’t run because there’s no measuring to do, Flex already knows
the height/width. As a result, don’t put anything critical in measure since
you can’t rely on its execution.

1.4.4.3 updateDisplayList()

The updateDisplayList is for drawing, and for child sizing and placement.
This method is passed two parameters, unscaledHeight and unscaledWidth. Here’s
the method signature:

updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void

These two values are the sizes that Flex has determined for your component.
They come from an explicit height/width OR the values determined
in the measure method OR they’re determined through measuring done
by the component's parent. While Flex has determined these values you can
override them here, though it’s better to do this sort of thing in measure.
However, in updateDisplayList you have total control of layout, and you can
do things that Flex might not.

updateDisplayList: drawing on the component

Sometimes you’ll use an override of updateDisplayList for drawing on your
component. For example, if your container doesn’t support a backgroundColor
you can draw it programmatically using the Graphics class, something like:

As you know by now, these graphic operations aren’t rendered to the screen
immediately, that won’t happen until the render phase.

updateDisplayList: sizing and laying out children

For composite components, updateDisplayList is where you set the size and
position of your child components. This generally involves calculations using
unscaledWidth and unscaledHeight as your bounds, and Adobe recommends you
do the following:

to get the size of a child UIComponent use getExplicitOrMeasuredWidth()

to set the size of a child UIComponent use setActualSize()

to get the position of a child UIComponent use x and y

to set the position of a child UIComponent use move()

The getExplicitOrMeasuredWidth is a convenience method that returns a number
which is explicitHeight if defined or measuredHeight if not.

To set the location of children you should use the move method rather than
setting values on the child’s x and y properties. The difference between
directly assigning values to the child’s x and y properties and using the
move method is that move changes the location of the component and then dispatches
its move event immediately, whereas setting the x and y properties changes
the location of the component and dispatches the event on the next screen
refresh. For details see Adobe's "Creating and Extending Adobe Flex
3 Components" Chapter 9. A similar efficiency gain is true for positioning:
to set your child component sizes you should use setActualSize rather than
their width and height properties.

Below is some code that illustrates doing layout operations within an override
of updateDisplayList.

The validation/validation processing described above applies not
only to component initialization, but also to the “life” of your component
– that is, your ongoing use of the component in your app, where it responds
to user events, Flex events, and your custom generated events. We’ll cover
this in the next section, the Component Lifecycle Phase 2 – Update.

Lifecycle Phase 2 - Update

The Update Phase represents the ongoing use of your component within your
application. Here’s a recap of the lifecycle primary phases:

Initialization

Update

Destruction

In the Update phase your component (your application, actually) is responding to
events, either Flex framework events or your custom events. In this phase
everything is event-driven – even user interactions like a mouse click
only execute code through the firing of an event. So, in this phase your application
does its work through event handlers and the invalidation/validation model.

When your component’s event handlers fire you can use the validation/invalidation
methods just as you did in the initialization phase –
to process property value changes, to add (and now potentially remove) children,
to draw on the component, etc.

Hopefully by now you can see how you’d use the lifecycle to do these tasks:

for a property change your setter would store the value in a
backing store variable and call invalidateProperties to ensure that commitProperties
executes in this frame. In commitProperties you’ll have code that commits
the value (and resets your dirty flag). You don't have to do this for all properties,
but for child properties and properties that depend on other properties you should
do this to avoid timing problems.

to add or remove children you’d again
call invalidateProperties because commitProperties is where dynamic children
are handled. You’d probably also call invalidateDisplayList since updateDisplayList
is where you’d adjust the layout of your child components.

to draw on the component you’d use an override of updateDisplayList,
ensuring it runs by calling invalidateDisplayList in your event handler.
Of course, you might just put your drawing routine in a method and call it
whenever it's needed. But if your drawing routine
might get called redundantly in a frame cycle then putting it in
updateDisplayList can ensure that 1) it runs only one in this frame cycle, and
2) it will use your component's final (for this frame) property values.

Before covering the Destruction Phase let’s revisit the Flash Player AVM and frame processing,
since this is especially relevant to efficiency in the Update phase.

Frames and the “Elastic Racetrack”

Since a primary focus of the Flex component lifecycle (and this article)
is efficiency it’s worth taking a moment to go a little deeper into Flash
player and Flex framework processing. This may help you understand why writing
efficient code is important not just for performance (faster response) but
also for avoiding rendering problems (jerky screen refreshes).

Earlier we looked at how the Flash player executes frames, cycling between
running code and rendering the results to the screen. Let’s decompose this
a bit more, taking into account the invalidation/validation processing. Here’s
a little more detail into what happens in the code execution phase:

just prior to the render phase Flex responds to invalidation flags by
executing validation methods as required

the code phase ends and the render phase begins

Ted Patrick, one of Adobe’s Flex architects, has termed this code execution
and rendering cycle the “elastic racetrack”. Why elastic? Because, while
the Flash player will always try to execute at the SWF’s framerate, it may
need to adjust things if you overload it with work. Overloading happens when your application
asks the Flash Player to do more processing than can “fit” in the current
frame (remember that each frame is sized for the current frame rate). When
a frame is overloaded the Flash player will “stretch” it – that is, increase
the time it is allotted – in order to fit in all the work to be done (because
Flex will always do the work you tell it to do, it’s lossless).

The above comes with a potential side effect – when frame processing is stretched
you’ll begin to see latency as the frame rate degrades.

Figure 2: Stretching of frames through
overloading

So, how can you overload and consequently stretch a frame? In the code phase
you could do this by processing a lot of data or by performing a long series
of complex calculations. In the render phase you could do it by loading the
screen with many nested and complex objects whose visual properties are constantly
changing, or you might have told Flex to do a lot of computationally intensive
drawing operations.

On the subject of overloading the rendering phase, it’s worth repeating something
said earlier – always keep in mind that code which can execute in a millisecond
can sometimes take much longer to actually render to the screen.

While this topic applies to the components you create, it also applies generally
to the entire application code, both ActionScript and MXML. What are some
of the things you should keep in mind to avoid overloading a frame’s processing?
Well, mostly we’re talking about general code efficiencies. There are plenty
of blogs posts and papers on this topic so I’ll mention just a few:

be wary of nesting containers unnecessarily or too deeply.
When Flex processes the display list tree it makes multiple
passes for measuring and layout, and if it needs to process a lot of tree nodes
this can get expensive in terms of time/processing/memory

changing a component’s styles after it’s on the stage can be
very expensive in terms of processing. Flex has to deal with style value inheritance,
so it must both determine the correct
values (processing the style tree for style values that might need to be inherited)
and then apply the visual changes (render ops).

if you use dirty flags don’t forget to reset them. Missing
a single flag reset won’t kill you, but add enough small inefficiencies and
they can add up to a stretching of the frame’s code exec phase

do as little work as possible in the constructor and configuration
steps, and in your setters; try to defer work to the validation step

Note that this primer's consideration of AVM processing is a simplification
to support explanation of the component lifecycle.
For example, the circular diagram showing the frame's
code and render phases is only a high-level view - in fact the code phase is itself
subdivided into many time slices, and the render portion of an "unstretched" frame cycle
is usually much smaller then the code execution portion).
For more information on this topic see the resources
listed at the end of this article (especially
Sean Christmann's analysis of AVM2).

Lifecycle Phase 3 - Destruction

The Destruction phase is the “death” of your component. The three primary
phases are recapped below, with a decomposition of the Destruction phase.

1. Initialization

2. Update

3. Destruction

3.1 detachment

3.2 garbage collection

3.1 Detachment

Detachment is the removal of a component from the display List. Detachment
is required before a component can be destroyed. However, note that sometimes
you’ll detach a component without destroying it. In fact this is good practice
if you’ll need that component again later, perhaps to add it to a different
parent – adding it back to the display list is cheaper than creating a new
one.

3.2 Garbage Collection

Garbage collection is the framework process for reclaiming memory. For a
component’s memory to be eligible for garbage collection it must have been
removed from the display list. There must also be no active references to
the component; if there is an active reference to your component then the
framework won’t GC it. Components that are not longer needed and have been
removed from the display list but still have active references are one source
of memory leaks in your application. One way to ensure the component is eligible
for garbage collection is to set any active reference to null.

Note that an “active reference” to the component includes event listeners
– even if you’ve set references to your component are null, if there are event
listeners on that component then it can’t be GC’d. One way to handle this
is to execute a removeEventListener for each addEventListener on the component.
However, you can also use the addEventListener parameter useWeakReference
when defining event listeners. Listeners that have been set with useWeakReference=true
won’t inhibit garbage collection.

Note that your component’s children will be garbage collected automatically
if their parent becomes available for GC (unless you’ve violated OOP and let
code external to your component obtain a reference to that child, and those
external references still point to the child).

Keep in mind that garbage collection doesn’t run constantly so your component’s
memory generally likely won’t be reclaimed immediately. Garbage collection
is a complex and somewhat arcane topic, worthy of a paper in itself. Especially
good are Grant Skinner’s posts on the topic.

Conclusion

The Flex component lifecycle is a set of processes for creating, managing
and destroying components. The lifecycle ensures that these processes execute
in the proper order and with a consistent set of triggers. These processes
are surfaced to you as protected methods. You can override these methods
to inject your own code into the lifecycle process. Done correctly this
can allow you to create more advanced and efficient components.

Keep in mind that you don't have to use the lifecycle for everything -
you can have an event handler that instantiates your component and sets
properties and adjusts the child layout in a single block of code
and generally you won't run into timing problems.
But often this isn't the most efficient way of doing things. As noted above,
what you do depends on your use case - tightly-bound one-off components require
less analysis, design and coding than components that you'll
be using many times in many different situations.

So, what about Flex 4? Well, Spark is build on top of Halo, and pretty much
everything covered above still applies. However, in Flex 4 most of the lifecycle
steps covered above have new subprocesses to handle the new skinning architecture.
So, you still have the createChildren lifecycle method, but in Flex 4 createChildren
may itself call new lifecycle methods like validateSkinState. The bottom
line: learning the Flex 3 lifecycle isn’t wasted time, and in fact gives you
a head start on understanding the internals of Flex 4.

Things we haven’t covered

This article was focused on the Flex component lifecycle and didn’t cover
related topics regarding custom Flex components (what about creating and dispatching
custom events! skins! metadata tags!). A book could be written about all
of this, and in fact one was, the Adobe document
“Creating and Extending Adobe Flex 3 Components” –
see the resources section below for more information on this
document.

Recommended Flex Component Lifecycle Resources

This primer may be useful as a starting point, but if you’re looking
for a “deep dive” into the topics covered here then you
should check out the resources listed below.

Adobe documentation

Here’s a livedocs entry point on the topic of the component lifecycle:

While Livedocs is great, sometimes it’s easier to work through a complex
topic when the info is in book form. Adobe has a 200+ page document called
“Creating and Extending Adobe Flex 3 Components” (from which the Livedocs
content is taken). This pdf document can be downloaded from Adobe’s
Flex
documentation page . Chapter 9 covers the component lifecycle
in depth.

And, as always, make use of the classdoc. Want info on the validation methods?
See the Protected Methods section of UIComponent’s classdoc entry.

Adobe TV videos

Adobe TV is generally excellent, and here are a few especially good 360|Flex
presentations on the lifecycle and component creation: