Improving startup performance

About startup performance

You could increase the startup time and decrease performance of your applications if you create too many objects or put too many objects into a single view. To improve startup time, minimize the number of objects that are created when the application is first loaded. If a user-interface component is not initially visible at startup, avoid creating that component until you need it. This is called deferred creation. Containers that have multiple views, such as an Accordion container, provide built-in support for this behavior. You can use ActionScript to customize the creation order of multiple-view containers or defer the creation of other containers and controls.

After you improve the actual startup time of your application as much as possible, you can improve perceived startup time by ordering the creation of containers in the initial view. The default behavior of Flex is to create all containers and their children in the initial view, and then display everything at one time. The user will not be able to interact with the application or see meaningful data until all the containers and their children are created. In some cases, you can improve the user's initial experience by displaying the components in one container before creating the components in the next container. This process is called ordered creation.

The remaining sections of this topic describe how to use deferred creation to reduce overall application startup time and ordered creation to make the initial startup time appear as short as possible to the user. But before you can fully understand ordered creation and deferred creation, you must also understand the differences between single-view and multiple-view containers, the order of events in a component's startup life cycle, and how to manually instantiate controls from their child descriptors.

About startup order

All Flex components trigger a number of events during their startup procedure. These events indicate when the component is first created, plotted internally, and drawn on the screen. The events also indicate when the component is finished being created and, in the case of containers, when its children are created.

Components are instantiated, added or linked to a parent, and then sized and laid out inside their container. The component creation order is as follows:

The following example shows the major events that are dispatched during a component's creation life cycle:

Major events dispatched during a component\xd5 s creation life cycle.

The creation order is different for containers and components because containers can be the parent of other components or containers. Components within the containers must also go through the creation order. If a container is the parent of another container, the inner container's children must also go through the creation order.

The following example shows the major events that are dispatched during a container's creation life cycle:

Major events dispatched during a container\xd5 s creation life cycle.

After all components are created and drawn, the Application object dispatches an applicationComplete event. This is the last event dispatched during an application startup.

The creation order of multiview containers (navigators) is different from standard containers. By default, all top-level views of the navigator are instantiated. However, Flex creates only the children of the initially visible view. When the user navigates to the other views of the navigator, Flex creates those views' children. For more information on the deferred creation of children of multiview containers, see Using deferred creation.

For a detailed description of the component creation life cycle, see Using container events.

Using deferred creation

By default, containers create only the controls that initially appear to the user. Flex creates the container's other descendants if the user navigates to them. Containers with a single view, such as Group, Box, Form, and Grid containers, create all of their descendants during the container's instantiation because these containers display all of their descendants immediately.

Containers with multiple views, called navigator containers, only create and display the descendants that are visible at any given time. These containers are the MX ViewStack, Accordion, and TabNavigator containers.

When navigator containers are created, they do not immediately create all of their descendants, but only those descendants that are initially visible. Flex defers the creation of descendants that are not initially visible until the user navigates to a view that contains them.

The result of this deferred creation is that an MXML application with navigator containers loads more quickly, but the user experiences brief pauses when he or she moves from one view to another when interacting with the application.

You can instruct each container to create their children or defer the creation of their children at application startup by using the container's creationPolicy property. This can improve the user experience after the application loads. For more information, see About the creationPolicy property.

You can also create individual components whose instantiation is deferred by using the createDeferredContent() method (for Spark containers) or the createComponentsFromDescriptors() method (for MX containers). For more information, see Creating deferred components.

About the creationPolicy property

To defer the creation of any component, container, or child of a container, you use the creationPolicy property. Every container has a creationPolicy property that determines how the container decides whether to create its descendants when the container is created. You can change the policy of a container using MXML or ActionScript.

The valid values for the creationPolicy property are auto, all, and none. The meaning of these settings depends on whether the container is a navigator container (multiple-view container) or a single-view container.

The creationPolicy property is inheritable when set on the MX Container or Spark SkinnableContainer class. This means that if you set the value of the creationPolicy property to none on an outer container, all containers within that container inherit that value of the creationPolicy property, unless otherwise overridden.

This inheritance does not apply to sibling containers. If you have two containers at the same level (of the same type) and you set the creationPolicy of one of them, the other container continues to have the default value of the creationPolicy property unless you explicitly set it.

Single-view containers

Single-view containers by default create all their children when the application first starts. You can use the creationPolicy property to change this behavior. The following table describes the values of the creationPolicy property when you use it with single-view containers:

Value

Description

all, auto

Creates all controls inside the single-view container. The default value is auto, but all results in the same behavior.

none

Instructs Flex to not instantiate any component within the container until you manually instantiate the controls.

When the value of the creationPolicy property is none, you generally set a width and height for that container explicitly. Normally, Flex scales the container to fit the children that are inside it, but because no children are created, proper scaling is not possible. If you do not explicitly size the container, it grows to accommodate the children when they are created.

To manually instantiate controls, you use the createDeferredContent() method (for Spark containers) or the createComponentsFromDescriptors() method (for MX containers). For more information, see Creating deferred components.

The following example sets the value of a Spark Panel container's creationPolicy property to auto, the default value:

<?xml version="1.0"?> 
<!-- layoutperformance/AutoCreationPolicy.mxml --> 
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark"> 
 
    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout> 
 
    <s:Panel id="myPanel" creationPolicy="auto"> 
        <s:Button id="b1" label="Get Weather"/> 
    </s:Panel> 
</s:Application>

The default behavior of all single-view containers is that they and their children are entirely instantiated when the application starts. If you set the creationPolicy property to none, however, you can selectively instantiate controls within the containers by using the techniques described in Creating deferred components.

Multiple-view containers

Containers with multiple views, such as the ViewStack and Accordion, do not immediately create all of their descendants, but only those descendants that are visible in the initial view. Flex defers the instantiation of descendants that are not initially visible until the user navigates to a view that contains them. The following containers have multiple views and, so, are defined as navigator containers:

When you instantiate a navigator container, Flex creates all of the top-level children. For example, creating an Accordion container triggers the creation of each of its views, but not the controls within those views. The creationPolicy property determines the creation of the child controls inside each view.

When you set the creationPolicy property to auto (the default value), navigator containers instantiate only the controls and their children that appear in the initial view. The first view of the Accordion container is the initial pane, as the following example shows:

First pane of the Accordion container.

When the user navigates to another panel in the Accordion container, the navigator container creates the next set of controls, and recursively creates the new view's controls and their descendants. You can use the Accordion container's creationPolicy property to modify this behavior. The following table describes the values of the creationPolicy property when you use it with navigator containers:

Value

Description

all

Creates all controls in all views of the navigator container. This setting causes a delay in application startup time and an increase in memory usage, but results in quicker response time for user navigation. You should generally not use all because of the performance hit that your application will take when it starts up.

auto

Creates all controls only in the initial view of the navigator container. This setting causes a faster startup time for the application, but results in slower response time for user navigation.

This setting is the default for multiple-view containers.

none

Instructs Flex to not instantiate any component within the navigator container or any of the navigator container's panels until you manually instantiate the controls.

To manually instantiate controls, you use the createDeferredContent() method (for Spark containers) or the createComponentsFromDescriptors() method (for MX containers). For more information, see Creating deferred components.

The following example sets the creationPolicy property of an Accordion container to all, which instructs the container to instantiate all controls for every panel in the navigator container when the application starts:

<?xml version="1.0"?> 
<!-- layoutperformance/AllCreationPolicy.mxml --> 
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark"> 
 
    <s:Panel title="Accordion"> 
        <mx:Accordion id="myAccordion" creationPolicy="all"> 
            <mx:VBox label="Accordion Button for Panel 1"> 
                <mx:Label text="Accordion container panel 1"/> 
                <s:Button label="Click Me"/> 
            </mx:VBox> 
            <mx:VBox label="Accordion Button for Panel 2"> 
                <mx:Label text="Accordion container panel 2"/> 
                <s:Button label="Click Me"/> 
            </mx:VBox> 
            <mx:VBox label="Accordion Button for Panel 3"> 
                <mx:Label text="Accordion container panel 3"/> 
                <s:Button label="Click Me"/> 
            </mx:VBox> 
        </mx:Accordion> 
    </s:Panel> 
</s:Application>

Setting a container's creationPolicy property does not override the policies of the containers within that container.

In the following example, the button1 control is never created because its immediate parent container specifies a creationPolicy of none, even though the outer container sets the creationPolicy property to all:

<?xml version="1.0"?> 
<!-- layoutperformance/TwoCreationPolicies.mxml --> 
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark"> 
 
    <s:Panel title="Outer Panel where creationPolicy=all" creationPolicy="all"> 
        <s:Panel title="Inner Panel where creationPolicy=none" creationPolicy="none"> 
            <s:Button id="button1" label="Click Me"/> 
        </s:Panel> 
    </s:Panel> 
</s:Application>

Creating deferred components

When you set a container's creationPolicy property to none, components declared as MXML tags inside that container are not created.

For Spark containers, you use the createDeferredContent() method to manually instantiate deferred components. This method is defined on the spark.components.SkinnableContainer class.

For MX containers, you use the createComponentsFromDescriptors() method to manually instantiate deferred components. This method is defined on the MX Container base class.

Using the createDeferredContent() method

You use the createDeferredContent() method to create deferred child components in a Spark container.

In the following example with a Spark container, the children of the Panel container are not instantiated when the application is first loaded, but only after the user clicks the button:
<?xml version="1.0"?> 
<!-- layoutperformance/CreationPolicyNoneSpark.mxml --> 
<s:Application     
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark"> 
 
    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout> 
 
    <fx:Script><![CDATA[ 
 
        private function createButtons(e:Event):void { 
            myPanel.createDeferredContent(); 
        } 
 
    ]]></fx:Script> 
 
    <s:Panel id="myPanel" title="Panel with Deferred Content" creationPolicy="none"> 
        <s:VGroup> 
            <s:Button id="b1" label="Hurley"/> 
            <s:Button id="b2" label="Jack"/> 
            <s:Button id="b3" label="Sawyer"/> 
        </s:VGroup> 
    </s:Panel> 
    
    <s:Button id="myButton" click="createButtons(event)" label="Create Buttons"/> 
 
</s:Application>

Only SkinnableContainer and containers that extend the SkinnableContainer class support deferred instantiation; Groups do not. When a Group is created, its children are always created. You cannot specify a creation policy on a Group.

Using the createComponentsFromDescriptors() method

Note: The createComponentsFromDescriptors() method is for MX containers. For Spark containers, use the createDeferredContent() method.

You use the createComponentsFromDescriptors() method of an MX container to create all the children of a container at one time.

The createComponentsFromDescriptors() method has the following signature:

 container.createComponentsFromDescriptors(recurse:Boolean):Boolean

The recurse argument determines whether Flex should recursively instantiate children of containers that are children of the top-level container. Set the parameter to true to instantiate children of the containers, or false to not instantiate the children. The default value is true.

On a single-view MX container, calling the createComponentsFromDescriptors() method instantiates all controls in that container, regardless of the value of the creationPolicy property.

In navigator containers, if you set the creationPolicy property to all, you do not have to call the createComponentsFromDescriptors() method, because the container creates all controls in all views of the container. If you set the creationPolicy property to none or auto, calling the createComponentsFromDescriptors() method creates only the current view's controls and their descendents.

Another common usage is to set the navigator container's creationPolicy property to auto. You can then call navigator .getChildAt(n).createComponentsFromDescriptors() to explicitly create the children of the n-th view.

Using the callLater() method

The callLater() method queues an operation to be performed for the next screen refresh, rather than in the current update. Without the callLater() method, you might try to access a property of a component that is not yet available. The callLater() method is most commonly used with the creationComplete event to ensure that a component has finished being created before Flex proceeds with a specified method call on that component.

All objects that inherit from the UIComponent class can open the callLater() method. It has the following signature:

 callLater(method:Function, args:Array):void

The method argument is the function to call on the object. The args argument is an optional Array of arguments that you can pass to that function.

The following example defers the invocation of the doSomething() method, but when it is opened, Flex passes the Event object and the "Product Description" String in an Array to that function:

 callLater(doSomething, [event, "Product Description"]); 
 ... 
 private function doSomething(event:Event, title:String):void { 
 	... 
 }

The following example uses a call to the callLater() method to ensure that new data is added to a DataGrid before Flex tries to put focus on the new row. Without the callLater() method, Flex might try to focus on a cell that does not exist and throw an error:

<?xml version="1.0"?> 
<!-- layoutperformance/CallLaterAddItem.mxml --> 
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark" 
    initialize="initData()"> 
 
    <fx:Script><![CDATA[ 
        import mx.collections.*; 
        private var DGArray:Array = [ 
            {Artist:'Pavement', Album:'Charred Walls', Price:11.99}, 
            {Artist:'Pavement', Album:'Good For You', Price:11.99}]; 
            
        [Bindable] 
        public var initDG:ArrayCollection; 
        //Initialize initDG ArrayCollection variable from the Array. 
        
        public function initData():void { 
            initDG=new ArrayCollection(DGArray); 
        } 
        
        public function addNewItem():void { 
            var o:Object; 
            o = {Artist:'Pavement', Album:'Tradio', Price:11.99}; 
            initDG.addItem(o); 
            callLater(focusNewRow); 
        } 
 
        public function focusNewRow():void { 
            myGrid.editedItemPosition = { 
                columnIndex:0,rowIndex:myGrid.dataProvider.length-1 
            }; 
        } 
        
    ]]></fx:Script> 
 
    <s:VGroup> 
        <mx:DataGrid id="myGrid" width="350" height="200" dataProvider="{initDG}"  editable="true"> 
            <mx:columns> 
                <fx:Array> 
                    <mx:DataGridColumn dataField="Album" /> 
                    <mx:DataGridColumn dataField="Price" /> 
                </fx:Array> 
            </mx:columns> 
        </mx:DataGrid> 
 
        <s:Button id="b1" label="Add New Item" click="addNewItem()"/> 
    </s:VGroup> 
    
</s:Application>

Another use of the callLater() method is to create a recursive method. Because the function is called only after the next screen refresh (or frame), the callLater() method can be used to create animations or scroll text with methods that reference themselves.

The following example scrolls ticker symbols across the screen and lets users adjust the speed with an HSlider control:

<?xml version="1.0"?> 
<!-- layoutperformance/CallLaterTicker.mxml --> 
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark"> 
    
    <fx:Script><![CDATA[ 
    
        [Bindable] 
        public var text:String = "SLAR:95.5....TIBA:42....RTF:34.15....AST:23.42"; 
        [Bindable] 
        public var speed:Number = 5; 
 
        public function initTicker():void { 
            theText.move( this.width+10, 0 ); // Start the text on the right side. 
            callLater(moveText); 
        } 
 
        public function moveText():void { 
            var xpos:Number = theText.x; 
            if( xpos-speed+theText.width < 0 ) { 
                xpos = this.width+10; // Start the text on the right side. 
            } 
            xpos -= speed; 
            theText.move(xpos,0); 
            callLater(moveText); 
        } 
 
        public function changeSpeed():void { 
            speed = speedSelector.value; 
        } 
        
    ]]></fx:Script> 
 
    <s:Panel title="Ticker Sample" width="400" height="200"> 
        <s:VGroup> 
                <mx:Canvas creationComplete="initTicker()" 
                    horizontalScrollPolicy="off" backgroundColor="red" color="white" 
                    width="400"> 
                <mx:Label id="theText" text="{text}" y="0"/> 
            </mx:Canvas> 
            <mx:HBox> 
                <mx:Label text="Speed:"/> 
                <mx:HSlider minimum="1" maximum="10" value="{speed}" 
                    id="speedSelector" snapInterval="1" tickInterval="1" 
                    change="changeSpeed()"/> 
            </mx:HBox> 
        </s:VGroup> 
    </s:Panel> 
</s:Application>

Navigation

Using Flex » Testing and automation

Adobe, Adobe AIR, Adobe Flash and Adobe Flash Player are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries and are used by permission from Adobe. No other license to the Adobe trademarks are granted.