Creating Custom UIComponents in Flex 2 May 22, 2010Posted by Tournas Dimitrios in Flex.
The Flex 2 framework provides a large assortment of components to handle the majority of your UI (user interface) needs. Taking advantage of these components is the quickest way to build a fully functional application, however, there are many times where you might find yourself in need of a component that does not exist. Fortunately, the Flex SDK offers plenty of extensibility for building custom UI components that can plug seamlessly into the existing framework.
The UIComponent Class
The UIComponent class is the least common denominator of all visual Flex components. That is to say, any class that is treated as a display object should have (at the very least) UIComponent in its inheritance chain. Flex has a very specific process for populating and maintaining the display list, and this class will provide most of the template behaviors it needs from your custom display objects. It’s important to note that many operations within the framework happen asynchronously to allow your applications to run as smoothly as possible, and therefore it’s up to you to adhere to the conventions for building your components, preserving the harmony of the system’s processes.
The UIComponent class is an indirect subclass of Sprite, which means that if you wish to use a different display object type, such as MovieClip or Bitmap, you will have to create such objects from within a custom UIComponent via composition (a UIComponent that has a Movieclip or Bitmap as opposed to a UIComponent that is a MovieClip or Bitmap).
There are two main procedures that need to be considered when building UIComponents: initialization and validation. During the creation cycle, both procedures (and a couple of additional steps) are processed. However, the validation procedure is additionally reused any time a visual change is triggered that may affect the system, whether externally to the component, or internally by the component. Figure 1 below demonstrates the creation cycle of a component.
Figure 1: The creation cycle of a UIComponent. The green region indicates the initialization procedure of the cycle, while the blue region indicates the validation procedure. The gold-colored steps identify methods that are provided for developers to override and implement custom behavior for, and the maroon-colored steps indicate dispatched events. The objects are ordered chronologically, where the thread processes from left to right as it works its way down each phase.
The Creation Cycle
As you can see in Figure 1, the creation cycle consists of five main phases: construction, attachment, initialization, validation, and completion. This cycle is performed internally, and is for the most part self sustained, with the exception being the initialization and validation procedures. Let’s begin by covering the five phases of the creation cycle, to understand what purpose each phase serves for the creation cycle.
As you would expect, the construction phase is the physical act of instantiating the component, using the new operator. You may opt to apply behavior at this phase by initializing properties or adding listeners in your constructor. Logic at this phase should be kept light and unobtrusive, however. Before you can understand what initialization logic should not be in the constructor, you should learn what initialization logic should be elsewhere within your component. Due to the asynchronous nature of the Flex framework, some properties cannot be initialized right away. The initialization procedure is specifically designed to account for this. We will cover more of this and the initialization procedure later in this series when we begin building our custom component.
The next phase after construction is attachment. This is where the component is added as a child to its parent display object. Naturally, the Event.ADDED event will be dispatched as a result. Also keep in mind that the component is not necessarily added to the display list at this point. In fact, the Application class itself isn’t even added to the stage when the first state of components are at this phase.
The initialization phase is a much more complex phase that depends on the individual characteristics of a UIComponent. As such, a procedure is run across its protected methods as shown in Figure 1. This initialization procedure is where the bulk of your visual-based initialization behavior should reside. Delegating relevant logic to the initialization procedure ensures that the system will be able to execute the procedure cleanly and predictably. The initialization procedure also dispatches FlexEvent.PREINITIALIZE and FlexEvent.INITIALIZE at the beginning and end of its procedure, respectively. The initialization phase only occurs once in a component’s lifetime.
The validation phase occurs in the creation cycle, but it is also the only phase whose procedure occurs frequently outside of the creation cycle as well. The procedure for validation is optimized for fluid interfaces, where many components may repeatedly alter their appearances as a response to any change within the interfaces’ compositions or externalized attributes, such as the browser’s dimensions. The framework minimizes wasted processes by only updating appearances at each frame interval, when the renderer redraws the screen.
Even then, validation procedures only occur when the component is flagged as invalidated. This procedure is also broken down into sub-sections to further minimize redundancy through selective invalidation. The initialization procedure invalidates all of these sub-sections to force a complete validation procedure for the creation cycle. We will cover more of this later in the series after populating the initialization procedure of our custom component.
Finally, the completion phase wraps up the creation cycle. In this phase, the FlexEvent.CREATION_COMPLETE event is dispatched. This event is popularly handled for setting up data-binding and other operations where you may want to be certain that the component and its children are allotted the maximum amount of time to properly initialize and render.
All custom components that are used as display objects should have UIComponent in its inheritance chain. The UIComponent class has two main procedures that subclasses can inject custom behavior into: initialization and validation. These procedures account for two of the five creation cycle phases, and the validation procedure is also used frequently outside of the creation cycle whenever visual changes occur within the application’s interface. These are the main principles to understand when building custom components. In the next lesson, we will begin building our own component, and you will see first-hand what role each step designated in the initialization procedure depicted in Figure 1 will play.