[Flexcerpts 201] - Observations on UIComponent Drawing
Posted by Phil Chung on March 26, 2007 2:45 PM | Permalink | Comments (342)

Since everything in the Flex framework essentially must be a UIComponent, we'll start with examining some of the inner workings of this class. In this Flexcerpt, we discuss how invalidation is implemented in UIComponent and why it is important when extending existing components or creating your own.

Invalidation is based on the premise that all displayable objects (anything that is a DisplayObject) are only drawn to the stage once every frame (since Flash is timeline based). In a nutshell, invalidation refers to delaying the drawing of a component until the next frame, so that we save processor cycles by only running that draw code once. "Drawing" can refer to things such as sizing (including measuring), displaying text, updating a skin, or changing any visible property of a component.

For example, what if the height value of a component was set 3 times during the same frame? If the component were to "redraw" itself immediately every time the height value was changed, it would be drawing 3 times, when it really only needs to draw itself once based on the last value that was set in that code block. This is a simple example, but when you consider that within the framework, there may be hundreds of lines of code executing when components are drawn (depending upon the complexity of your app), obviously, we want to prevent unnecessary redraws whenever we can. Enter invalidation...

There are 3 invalidation methods implemented in the framework:

  • invalidateProperties (commits properties)
  • invalidateSize (does measuring)
  • invalidateDisplayList (does layout)

These methods are called interally within Flex components when the component has something done to it that requires it to be redrawn. Often, more than one of these will be called within the same method. Here is an overview of the code execution that occurs with each of the invalidation methods (not all called methods are shown here to simplify things a bit):

> UIComponent.invalidateProperties() > LayoutManager.invalidateProperties() > enterFrame/render > LayoutManager.validateProperties() > UIComponent.validateProperties() > UIComponent.commitProperties()
>UIComponent.invalidateSize() > LayoutManager.invalidateSize() > enterFrame/render > LayoutManager.validateSize() > UIComponent.validateSize() > UIComponent.measureSizes() > UIComponent.measure()
>UIComponent.invalidateDisplayList() > LayoutManager.invalidateDisplayList() > enterFrame/render > LayoutManager.validateDisplayList() > UIComponent.validateDisplayList() > UIComponent.updateDisplayList()

As you can see, the flow is very similar among these methods. So why does this really matter? Well, here are a few things I took from this: