Developing Flex 4 Components: Anatomy of a Component
Now that you have seen all the components present within Flex 4.0, let's focus on what actually makes up the structure of a component and the core behaviors and functionality that you need to provide for it to operate within the Flex framework. In this chapter, you get a clear understanding of how to structure your components, both in ActionScript and MXML, and which component is most suitable as the base class for your own components. Finally, you get an overview of a unique type of component, but I'll save that surprise for you until later in this chapter.
Component Life Cycle
Regardless of how simple or complex you make your components, there is one constant: Your component needs to be instantiated and when it does, it needs to be able to initialize itself and create and display any assets it requires. If it is interacted with or data changes that it consumes or manages, it needs to notify not only external elements of your application that it has changed in some way, but also most likely itself and its own children. This is commonly referred to as the component life cycle. Figure 3.1 shows an illustration of the actual cycle.
Figure 3.1 Component life cycle
As part of this cycle, various methods are invoked, events dispatched, and properties set, some only once during the initialization of the component and others numerous times depending on user, data, or state-driven influences. As Figure 3.1 shows, the Constructor and createChildren() methods are invoked only once during the entire life cycle of the component, whereas the commitProperties(), measure(), and updateDisplayList() methods can be invoked repeatedly, depending on the type of influence that has been placed on the component. Each of these core component framework methods has their access modifier set to protected to avoid unnecessary or accidental direct interaction from external sources, but at the same time, enables any subclasses to inherit and invoke them.
Within your component, you can tailor all or none of these methods and any number in between; if you do need to alter one, you need to make sure you meet two requirements of inheritance:
- The method must invoke the super class or method, passing the relevant parameters if present.
- The method must use the override keyword to indicate that you want to add or alter the functionality of that method that already exists within the parent class method within your component.
The following code shows an overridden updateDisplayList() method:
// marked as override so we can change its functionality override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { /* Call the super.methodName so that additional functionality that is declared within it can be executed */ super.updateDisplayList(unscaledWidth, unscaledHeight); // Your code for your component included here _myTextDisplay.setActualSize(); ... }
As you can see, it is fairly straightforward to override a component method ready to add the specific functionality that your component requires. Word to the wise, however: Don't override a method if you aren't going to add any additional functionality. Although it doesn't affect the component, it adds needless code that provides no benefit and reduces the legibility of your class when others look through it to see how it operates. For example, taking the previous code and just leaving it as illustrated in the following provides no inherent value beyond just bloating your code:
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth,unscaledHeight); }
With those points in mind, let's look at which method performs what role within this life cycle and how you can leverage this process to produce rich components without having to re-create functionality that is already there.