I had to meet Adobe Flex in almost combat conditions. Suddenly it took to write something working, using only examples from the Internet and the help of senior comrades. Nearby there was not a single book on Flex, and there was also time for reading, which had a strong impact on the theoretical basis. Much was done to the touch by simple Russian trial and error. Well, I had to try decently. Looking back now, I realized that many rakes could have been avoided if there was a simple introductory article at hand explaining what was happening. Under the cat collected 3 questions, due to a misunderstanding of which I most often had problems. I hope the answers to them will help beginners to quickly understand the intricacies of building components of this framework.
Let's start, as usual, from birth
Question: I create a component showing pictures of naked women with some internal interface elements. Where it is better to initialize them, and what is this createChildren?
In the class constructor it is better not to do anything resource-intensive. It is usually used only for initializing variables and adding eventListeners.
To create nested elements, a special function createChildren () is provided in the flex. It is automatically called when a component is added to any displayList. Therefore, if we need something inside, we need to redefine createChildren and put the code that creates the inner elements there. There is one subtlety here - be sure to check if the next spicy picture has already been created. This was done for two reasons. The first is that createChildren can be called several times if your component moves from one displayLista to another. For example itemRenderer'y, which are often removed and re-added. Thus, we can get many copies of the same naked women, and this, as we know, is not interesting. The second reason is the ability to change behavior in the descendant classes. If the heir class decides that instead of Pamela Anderson, Angelina Jolie should be in the upper left corner, he will create this internal element in the desired form, and then call super.createChildren (). The parent component will see that the element has already been created and will not bother to work.
')
Example:
override protected function createChildren (): void{// check if the component already exists
If
(! OurNestedComponent
){// if not, then create
ourNestedComponent
= new NestedComponent ();addChild
( ourNestedComponent
);}// don't forget to call createChildren up the hierarchy
super . createChildren ();}Now the most interesting thing is life and user interaction.
Question: I want to change a couple of properties, is there also some kind of magic for this?There is, and very comfortable. It is called deferred validation. Do not be intimidated by the word "validation", in this context it means changing the state of a component: applying properties, redrawing the background, changing the position of internal elements, and so on. How it works? Changing properties directly in property setters is a bad idea. Firstly, it can negatively affect the visual smoothness of the interface when the user acts. Especially if the changes are resource intensive. Secondly, if one property depends on another, or the properties must be applied in a certain order, you will have to think about some sort of wait and synchronization mechanism. Deferred validation is a way to avoid all this. Instead of immediately applying any property, it is postponed, and the change takes effect immediately before the screen is drawn.
Validation of changes occurs in three stages:
- Properties change (commitProperties function)
- Preferred dimensions are calculated (measure function)
- The actual dimensions, dimensions and coordinates of the internal elements are calculated, and everything that should be drawn is drawn. (updateDisplayList function)
Each of these functions is called automatically during the render event for all components awaiting validation. To mark a component as pending validation, you must call the special component function: invalidateProperties () for commitProperties, invalidateSize () for measure and invalidateDisplayList () for updateDisplayList.
We now turn to practice and in passing tell you more about each of the points of validation.
Stage one - the commitProperties function
For example, in our gallery of "celebrities", in addition to the photos themselves, there are some controls. The user can change the section using the drop-down menu and adjust the degree of stripping with the slider, as well as change these parameters at the same time through certain “fayor”. Thus, there are two properties: “section” and “degree of undressing”, which can vary both individually and simultaneously. If you process the changes directly in the setters, you may have to do extra work. Indeed, if a user chooses a photo from the “Paris Hilton” section with a degree of stripping “extremely shameless”, you will first have to load the “Paris Hilton” section with some default stripping, and only then apply “extremely shamelessly” and load pictures by new . To avoid this, in the setters we only save the new state, and the change itself is carried out in the commitProperties function.
Example:
public function set section
( value
: String
): void{_section
= value
; // save the new value to a private variable
_sectionChanged
= true ; // remember what exactly has changed
invalidateProperties
(); // sign the component on the commitProperties call at the next iteration
}public function set nudeDegree
( value
: String
): void{_nudeDegree
= value
;_nudeDegreeChanged
= true ;invalidateProperties
();}override protected function commitProperties (): void{If
( _sectoinChanged
|| _nudeDegreeChanged
){// here we do all the work of loading the right photos
...
// remove the flag about the change
_sectionChanged
= false ;_nudeDegreeChanged
= false ;}// apply other properties
...
// don't forget to call commitProperties up the hierarchy
super
. commitProperties ();}With commitProperties, all our properties are applied once and in the sequence we need.
The next validation step is the measure () function.
This function is used to calculate the preferred (measuredWidth and measuredHeight) and minimum (measuredMinWidth and measuredMinHeight) dimensions of the component. Parent components use these values ​​for sizing if they are not explicitly stated. For example, if we want our gallery to automatically resize based on the number of images inside, we must calculate the preferred sizes. To do this, we will add a code to the measure function that will add the dimensions of all the images, as well as take into account the dimensions of the controls, and assign the obtained values ​​to measuredWidth and measuredHeight.
To subscribe a component to the measure function, you must call the invalidateSize () function. The measure function is executed only if the dimensions of the component are not specified, and calculates default values, otherwise the specified dimensions are used.
Finally, the final stage of validation: the updateDisplayList function
Everything related to the resizing or coordinates of any internal elements should be here. updateDisplayList takes two parameters: unscaledWidth and unscaledHeight. They are determined by the parent component, and they (and not width and height) should be used when calculating the coordinates and dimensions of the internal components.
It is also necessary to follow the rules for changing the properties of internal components:
- resize them using the setActualSize (width, height) function, rather than straight, by setting specific values
- change coordinates using the move (x, y) function, rather than straight, setting specific values ​​of x and y
- These rules will in most cases eliminate problems with the wrong behavior of components.
Sizes of components
Question: In the flex there are so many different properties denoting dimensions. Why are they all?
The sizes are set in several ways.
- Preferred dimensions (measuredWidth, measuredHeight). They are determined by the component itself. These dimensions are used unless specifically indicated otherwise, and if the component has enough space for that. If, for example, you place a button through MXML and do not specify dimensions, it will be exactly the same size as defined using the measure function
- Minimum dimensions (measuredMinWidth and measuredMinHeight). They are also determined by the component itself. In the case where dimensions are not specified (those used by measuredWidth and measuredHeight), and preferred dimensions are larger than the dimensions of the parent component, it tries to reduce it to fit the component into itself. The minimum sizes just set the lower limit for these attempts.
- Dimensions in percentages (percentageWidth and percentageHeight) are the dimensions in percentages of the dimensions of the parent component.
- The sizes specified explicitly (explicitWidth and explicitHeight) are the dimensions of the component in pixels. Also set directly through the width and height
The sizes in percent and the sizes in pixels do not depend on the preferred and minimum and can take any values.
Read on:
www.slideshare.net/Constantiner/flex-component-lifecycle-overview - slides from the wonderful presentation by Pavel Kozhin, unfortunately without sound. This is almost all that I found on the topic in the Russian Internet.
Implementing the component [ENG] is a live view from Adobe itself. In detail, but a little dry in English. Nevertheless, the reading is required.