Accessibility

Table of Contents

Flex Application Performance: Tips and Techniques for Improving Client Application Performance

Using Layouts, Hierarchy, and Containment Properly

The biggest Flex performance danger is yielding to the temptation to use containers randomly. Using too many containers dramatically reduces the performance of your application. This is the number one performance danger that Flex developers succumb to—and luckily it is 100 percent avoidable. The performance penalty occurs because Flex layout containers and their children follow sizing and measuring algorithms that determine x,y positions, preferred sizes, and styles. These calculations are resource-intensive; it is these calculations, coupled with Flash Player drawing complex objects, that cause a noticeable delay when starting a Flex application or when instantiating a new view in a navigator container. One principle dramatically speeds up application startup and interactivity time: Avoid unnecessary container nesting.

Avoid Nesting Containers Many Levels Deep

A good rule of thumb is to avoid excessive container nesting. At first, you might find it difficult to pinpoint superfluous container nesting. The following describes some of the more common cases of nesting containers and offers useful tips for choosing and using containers.

Below are a few examples of deeply nested code:

<mx:VBox>
  <mx:HBox>
    <mx:Form>
      <mx:FormItem>
       .....
       ...
      </mx:FormItem>
    </mx:Form>
  </mx:HBox>
</mx:VBox>

and

<mx:Grid>
  <mx:GridRow>
    <mx:GridItem>
      <mx:VBox>
       <mx:Button />
      </mx:VBox>
    </mx:GridItem>
  </mx:GridRow>
</mx:Grid>

When you nest containers, each container instance runs measuring and sizing algorithms on its children (some of which are containers themselves, so this measuring procedure can be recursive). When the layout algorithms have processed, and the relative layout values have been calculated, Flash Player draws the complex collection of objects comprising the view. By eliminating unnecessary work at object creation time, you give your application a boost and the performance benefits are readily apparent.

Typically, nesting fewer containers provides good results with respect to creation time. If you find yourself nesting many levels deep, re-evaluate your choice of containers. Perhaps you can achieve the same layout with a different layout container in conjunction with style attributes, such as horizontal and vertical alignment, margins, spacers, and gaps. You can use margins and gaps to manipulate the space around controls and between the edge of controls and the edge of their parent containers. You can use spacer objects to fill unwanted space or to push controls around the screen. You can also align controls horizontally or vertically within their container. For example, take a look at the layout in Figure 1.

You can achieve this layout without using a Grid container.

Figure 1. You can achieve this layout without using a Grid container.

It is tempting to use a Grid container to achieve this layout:

<mx:Grid>
  <mx:GridRow>
    <mx:GridItem>
      <mx:Button label="Visa"/>
    </mx:GridItem>
    <mx:GridItem>
      <mx:Button label="MasterCard"/>
    </mx:GridItem>
    <mx:GridItem>
      <mx:Button label="Diner's Club"/>
    </mx:GridItem>
    <mx:GridItem>
      <mx:Button label="AmEx"/>
    </mx:GridItem>
  </mx:GridRow>
</mx:Grid>

However, this code is unnecessarily bloated. In fact, you can easily revise the code so that it looks exactly like Figure 1. The following snippet uses less code and results in a faster creation time and a slightly smaller SWF output.

<mx:HBox>
  <mx:Button label="Visa"/>
  <mx:Button label="MasterCard"/>
  <mx:Button label="Diner's Club"/>
  <mx:Button label="AmEx"/>
</mx:HBox>

Steven Webster, an active Flex community member, has an excellent entry in his blog on the dangers of nested containers, as well as tips on how to avoid nesting.

Absolute Positioning and Sizing

The Flex container classes are relative layout containers that arrange contents on the screen for you. However, the calculations to decipher how big each container and its children are, as well as where to place them, can potentially be resource-intensive. Here are two tips that can help reduce these calculations:

  • Hard-code object positions—Hard-coding object positions can save a lot of time because the Flex layout containers do not need to calculate object positions at runtime. If you want to go this route, you can only use the Canvas container. Other types of containers, like the VBox container, do not respect absolute positions. When using the Canvas container, you must explicitly declare the x and y properties of all the Canvas children. If you omit setting x and y properties, the Canvas container's children lay out on top of each other at the default x,y coordinates (0,0). Absolute positioning does not work well if you want your application to resize when the browser window resizes. Using the Canvas container to create faster layouts should be a last-resort solution.
  • Hard-code object widths and heights—Hard-coding object widths and heights can also save time, because the Flex layout containers do not need to calculate the size of the object at runtime. By hard-coding container or control widths or heights, you lighten the relative layout container's processing load and subsequently speed up container and control creation time. This technique works with any container or control.

Use Grid Containers Wisely

Think of a Grid container as a layout choice already pushing the deep nesting rule. Grid, GridItem and GridRow are all containers in their own right, although GridItem and GridRow are only used in conjunction with the Grid container. You should only use a Grid container when your controls must line up both horizontally and vertically. Developers often gravitate to the Grid container, because they see the similarity to the HTML <table> tag. However, as a Flex developer, you can choose from multiple container choices to position objects (and some are less resource-intensive to use then others). This is not true of the HTML world, where <table> is really the only choice. The following code provides an example of when to use a Grid container—the controls in the different columns and rows must all line up (see Figure 2):

<mx:Grid>
 <mx:GridRow>
  <mx:GridItem><mx:TextInput text="TextInput"/></mx:GridItem>
  <mx:GridItem><mx:NumericStepper/></mx:GridItem>
  <mx:GridItem><mx:TextInput text="TextInput"/></mx:GridItem>
  <mx:GridItem><mx:NumericStepper/></mx:GridItem>
 </mx:GridRow>
 <mx:GridRow>
  <mx:GridItem><mx:Button label="button"/></mx:GridItem>
  <mx:GridItem><mx:DateField /></mx:GridItem>
  <mx:GridItem><mx:Button label="button"/></mx:GridItem>
  <mx:GridItem><mx:DateField /></mx:GridItem>
 </mx:GridRow>
 <mx:GridRow>
  <mx:GridItem><mx:TextInput text="TextInput"/></mx:GridItem>
  <mx:GridItem><mx:NumericStepper/></mx:GridItem>
  <mx:GridItem><mx:TextInput text="TextInput"/></mx:GridItem>
  <mx:GridItem><mx:NumericStepper/></mx:GridItem>
 </mx:GridRow>
</mx:Grid>
This UI is the perfect candidate for a Grid container.

(+) View Larger

Figure 2. This UI is the perfect candidate for a Grid container.

Some common misuses of Grid containers include the following:

  • Using the Grid container when you want to left-justify or right-justify controls in the same container (see Figure 3). Developers often try to do this using the following code:

    <mx:Grid borderStyle="solid" width="400">
     <mx:GridRow>
      <mx:GridItem horizontalAlign="left">
       <mx:Button label="left" />
      </mx:GridItem>
      <mx:GridItem horizontalAlign="right">
       <mx:Button label="right" />
      </mx:GridItem>
     </mx:GridRow>
    </mx:Grid>
    

    However, using an HBox container with a Spacer object to fill unwanted space works the exact same way, as shown in the following snippet:

    <mx:HBox borderStyle="solid" width="400">
      <mx:Button label="left" />
      <mx:Spacer width="100%" />
      <mx:Button label="right" />
    </mx:HBox>
    

    You can achieve this left-justify/right-justify layout without a Grid.

    Figure 3. You can achieve this left-justify/right-justify layout without a Grid.

  • Using a Grid container as a child of a Repeater object when alternate mechanisms would work better. Take a look at the Repeater object in Figure 4.

    Using a Grid container in a Repeater to achieve this layout is resource-intensive

    (+) View Larger

    Figure 4. Using a Grid container in a Repeater object to achieve this layout is resource-intensive.

    This Repeater object repeats a heavily populated Grid container with labels retrieved from a web-service. Creating just one of these Grid containers would take a noticeable creation time, but repeating this Grid many times is worse.

As your Flex repertoire expands, you will see that there are alternate containers and controls that you can easily customize to meet your needs. For example, you can achieve the layout shown in Figure 4 with a List control and a custom cell renderer. You can use a cell renderer with any list-based component to create custom-formatted cells, and the cells can be different heights. The Flex documentation will have more information and examples on how to create a custom cell renderer. The performance of a List control with a custom cell renderer is spectacularly better than with a repeated Grid container. Or you can use the HorizontalList and TileList controls to create custom controls in an HBox or Tile-like layout. These controls perform very well because they only create elements visible in the initial view and then the user can scroll to see subsequent elements—instantiation time is quicker.