Your SlideShare is downloading. ×
0
Page 0 of 59<br />Flex 4 Components from the Fire Hose<br />Michael Labriola<br />Senior Consultants<br />Digital Primates...
Who am I?<br />Michael Labriola<br />Senior Consultant<br />Digital Primates<br />Client side architect specializing in Ad...
Pregame<br />Pre-compile, compile and linking time<br />3<br />
What are we going to cover?<br />We are going to start with MXML <br />We are going to see what it looks like after it is ...
Here is our source code<br />Firehose.mxml is our main application file. It consists of the following pieces:<br /><?xml v...
Generation<br />This code turns into many generated files. Most important to us are:<br />ActionScript version of your App...
Application Subclass<br />The first piece of generated code is the Application subclass. When the application is subclasse...
Frame metadata<br />Page 3 of 59<br />The following metadata is added to the application subclass:<br />[Frame(extraClass=...
MXML Properties<br />Page 3 of 59<br />A Bindable public property is created for the MXML instances so that you can refer ...
Factory Functions<br />Page 3 of 59<br />For each MXML tag, a factory function is created to build the corresponding objec...
Factory Functions<br />Page 3 of 59<br />An Array of all of the components is then created invoking each of those methods ...
Multiple Controls<br />Page 3 of 59<br />For example, if we had three buttons as peers, the code would like this:<br /><s:...
Non Skinnable<br />Page 3 of 59<br />Flex 4 is full of new classes to learn. Let’s start by discussing an old favorite, UI...
Skinnable*<br />Page 3 of 59<br />Two additional new classes in Flex 4 worth noting at this time: SkinnableComponent and S...
mxmlContentFactory<br />Page 3 of 59<br />The goal of all of the work in the generated application code so far has been to...
IDeferredInstance<br />Page 3 of 59<br />To be an IDeferredInstance a class must have a single method:<br />public functio...
DeferredInstanceFromFunction<br />Page 3 of 59<br />Our generated code is simply a function and the mxmlContentFactory exp...
Nested Controls<br />Page 3 of 59<br />The factory functions generated change a bit when we have nested controls:<br /><s:...
Nested Controls Generated<br />Page 3 of 59<br />private function _Firehose_Array1_c() : Array {<br />var temp : Array = [...
Nested Group<br />Page 3 of 59<br />In the case of the nested group, you may notice that the mxmlContent property is set, ...
Application Subclass<br />The next major piece of generated code is the SystemManager subclass. Several important things o...
IFlexModuleFactory<br />Page 3 of 59<br />The newly created SystemManager subclass will implement IFlexModuleFactory and I...
registerImplementation()<br />Page 3 of 59<br />This method allows the Flex framework, and you should you wish, to registe...
getImplementation()<br />Page 3 of 59<br />This method allows you to getImplementations that were previously registered. S...
create()<br />Page 3 of 59<br />The create() method is where the magic happens and your app will be instantiated:<br />ove...
info()<br />Page 3 of 59<br />The info() method returns a generic object filled with required and optional properties used...
info()<br />Page 3 of 59<br />In this code snippet from info() you can see where the mixins are specified. This is the way...
Mixin<br />Page 3 of 59<br />Mixin classes are decorated with the Mixin metadata and have a public static method named ini...
Btn Binding Setup<br />Page 3 of 59<br />Earlier I mentioned that Flex creates a public var for btn on the host component ...
Btn Binding Setup<br />Page 3 of 59<br />[Bindable(event="propertyChange")]<br />public function get btn():spark.component...
Watcher Setup<br />Page 3 of 59<br />If you add one Bindable properties to your application. You receive the following add...
lblMe Binding Setup<br />Page 3 of 59<br />private function _Firehose_bindingsSetup():Array {<br />varresult:Array = [];<b...
lblMe Watcher Setup<br />Page 3 of 59<br />public function setup(target:Object,<br />propertyGetter:Function,<br />staticP...
Application Constructor<br />Page 3 of 59<br />if (_watcherSetupUtil == null) {<br />varwatcherSetupUtilClass:Object = 	ge...
GAME TIME<br />Loading and Running<br />35<br />
SWF Load<br />Page 3 of 59<br />You begin loading your SWF into the browser of your choice. However, you need to remember ...
SystemManager Constructor<br />Page 3 of 59<br />The SystemManager’s constructor is called where it does a few things like...
SystemManager Constructor<br />Page 3 of 59<br />The final line in the SystemManager’s Constructor:<br />if (root && root....
init()<br />Page 3 of 59<br />One the initHandler() is called, the world gets more interesting. <br />This method does a l...
initialize()<br />Page 3 of 59<br />This method is responsible for creating the PreLoader. The PreLoader itself is a logic...
kickOff()<br />Page 3 of 59<br />When both of these conditions are true (and they can happen in any order) either the prel...
initializeTopLevelWindow()<br />Page 3 of 59<br />This method does a lot of work to ensure we load correctly and size appr...
ChildManager()<br />Page 3 of 59<br />Inside of ChildManager, the create() method that was overridden by the compiler is c...
ChildManager() cont<br />Page 3 of 59<br />Inside of the ChildManager, the addingChild() method is called.<br />This metho...
PreInitialize<br />Page 3 of 59<br />The Application initializes several managers and the context menus before beginning t...
createChildren()<br />Page 3 of 59<br />Immediately after dispatching the event, the createChildren() method is called. Th...
validateSkinChange()<br />Page 3 of 59<br />The validateSkinChange() checks for an existing skin and detaches it if it exi...
attachSkin()<br />Page 3 of 59<br />The attachSkin() method finds the correct skin for this component, instantiates it, an...
attachSkin()<br />Page 3 of 59<br />At this point, the owner and hostComponent of the skin are set. The hostComponent of a...
attachSkin()<br />Page 3 of 59<br />After the skin is created, the styles of the component are passed to the skin for use....
Skin PreInitialize<br />Page 3 of 59<br />The skin now broadcasts its FlexEvent.PREINITIALIZE. <br />It means the skin is ...
Skin createChildren()<br />Page 3 of 59<br />Immediately after dispatching the event, the createChildren() method is calle...
addElement()<br />Page 3 of 59<br />Immediately after dispatching the event, the createChildren() method is called. <br />...
IVisualElement<br />Page 3 of 59<br />IVisualElement is a new interface to spark which defines the properties that must be...
elementAdded() cont<br />Page 3 of 59<br />As the new visual elements are added to the skin, the skin’s elementAdded() met...
elementAdded()<br />Page 3 of 59<br />In the case where the element is an IGraphicalElement (an interface that descends fr...
elementAdded()<br />Page 3 of 59<br />In all other cases, the element is assumed to be a displayObject and added to the di...
More Recursion<br />Page 3 of 59<br />The addition of each of these elements to the display list causes their initialize()...
Back Up<br />Page 3 of 59<br />Starting from the deepest point on the stack of children, each child does the following ope...
Child Additions<br />Page 3 of 59<br />Starting from the deepest point on the stack of children, each children performs th...
FlexEvent.INITIALIZE<br />Page 3 of 59<br />The initialize event is always broadcast by the inner most child first.<br />I...
findSkinParts()<br />Page 3 of 59<br />After each skin initializes, you return to the attachSkin() method where the skin w...
partAdded()<br />Page 3 of 59<br />As each of these parts is identified and the reference provided, the partAdded() method...
partAdded()<br />Page 3 of 59<br />The default behavior of the partAdded() method is to dispatch a SkinPartEvent.PART_ADDE...
SkinStates<br />Page 3 of 59<br />After all parts are added, the invalidateSkinState() method is called.<br />When you def...
SkinStates<br />Page 3 of 59<br />The invalidateSkinState() method informs the component that the skin needs to know its n...
Deferred<br />Page 3 of 59<br />After all of the skins are attached, the stack returns to the createChildren() method<br /...
Deferred Creation<br />Page 3 of 59<br />This means initialize is a bit trickier.<br />Skins for a class are created befor...
Recursion Complete<br />Page 3 of 59<br />One all of the children are initialized from the inner most to the outer, you wi...
Invalidation<br />Page 3 of 59<br />All of this invalidation effectively adds each of these components to a priority queue...
Invalidation<br />Page 3 of 59<br />After each component has had a chance to complete all necessary validation, it is mark...
creationComplete<br />Page 3 of 59<br />The FlexEvent.CREATION_COMPLETE means that all layout, sizing and positioning is c...
Application Visible<br />Page 3 of 59<br />Once all of the children have broadcast their creationComplete event, the time ...
Application Complete<br />Page 3 of 59<br />The act of making the application a child of the system manager is among the l...
Questions<br />Page 3 of 59<br />?<br />
Page 59 of 59<br />Me<br />Michael Labriola<br />http://twitter.com/mlabriola<br />
Upcoming SlideShare
Loading in...5
×

Flex 4 Components

2,479

Published on

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,479
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
30
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Transcript of "Flex 4 Components"

  1. 1. Page 0 of 59<br />Flex 4 Components from the Fire Hose<br />Michael Labriola<br />Senior Consultants<br />Digital Primates<br />twitter.com/mlabriola<br />
  2. 2. Who am I?<br />Michael Labriola<br />Senior Consultant<br />Digital Primates<br />Client side architect specializing in Adobe Flex<br />Architect and developer of Fluint<br />Lead architect and developer of FlexUnit 4.x<br />Team Mentor<br />Co-Author of Flex Training from the Source Series<br />Geek<br />Page 2 of 59<br />
  3. 3. Pregame<br />Pre-compile, compile and linking time<br />3<br />
  4. 4. What are we going to cover?<br />We are going to start with MXML <br />We are going to see what it looks like after it is compiled<br />We are then going to walk through each class on the way from instantiation through display<br />We will cover as much as we can before time runs out<br />Page 3 of 59<br />
  5. 5. Here is our source code<br />Firehose.mxml is our main application file. It consists of the following pieces:<br /><?xml version="1.0" encoding="utf-8"?><br /><s:Application <br />xmlns:fx="http://ns.adobe.com/mxml/2009" <br />xmlns:s="library://ns.adobe.com/flex/spark"><br /> <s:Button id="btn" label="Click Me"/><br /></s:Application><br />Page 3 of 59<br />
  6. 6. Generation<br />This code turns into many generated files. Most important to us are:<br />ActionScript version of your Application subclass<br />ActionScript subclass of the system manager<br />Getter/Setter generation for mxml properties<br />Flex Init Mixin<br />Styles, styles and more styles<br />Page 3 of 59<br />
  7. 7. Application Subclass<br />The first piece of generated code is the Application subclass. When the application is subclassed, several important things occur:<br />Frame metadata is specified<br />Properties are created for MXML components in the document<br />Factory functions are created for the MXML content<br />The mxmlContentFactory is set<br />Style declaration setup is deferred for a bit<br />Page 3 of 59<br />
  8. 8. Frame metadata<br />Page 3 of 59<br />The following metadata is added to the application subclass:<br />[Frame(extraClass="_Firehose_FlexInit")]<br />[Frame(factoryClass="_Firehose_mx_managers_SystemManager")]<br />The first line ensures the inclusion of the Firehose_FlexInitmixin<br />The second line specifies that the Firehose_mx_managers_SystemManager is the bootstrapped root class for your swf<br />
  9. 9. MXML Properties<br />Page 3 of 59<br />A Bindable public property is created for the MXML instances so that you can refer to these by id in the Application<br />[Bindable]<br />public varbtn : spark.components.Button;<br />Note this corresponds to the id of the object in the MXML<br /><s:Button id="btn" label="Click Me"/><br />
  10. 10. Factory Functions<br />Page 3 of 59<br />For each MXML tag, a factory function is created to build the corresponding object and set its properties<br />private function _Firehose_Button1_i():Button {<br />var temp : Button = new spark.components.Button();<br />temp.label = "Click Me";<br /> temp.id = "btn";<br /> if (!temp.document) temp.document = this;<br />btn = temp;<br />BindingManager.executeBindings(this, "btn", btn);<br /> return temp;<br />}<br />
  11. 11. Factory Functions<br />Page 3 of 59<br />An Array of all of the components is then created invoking each of those methods and adding the result to the Array<br />private function _Firehose_Array1_c() : Array<br />{<br />var temp : Array = [_Firehose_Button1_i()];<br /> return temp;<br />}<br />
  12. 12. Multiple Controls<br />Page 3 of 59<br />For example, if we had three buttons as peers, the code would like this:<br /><s:Button id="btn1" label="Click Me"/><br /><s:Button id="btn2" label="Click You"/><br /><s:Button id="btn3" label="Click It"/><br />private function _Firehose_Array1_c() : Array {<br />var temp : Array = [_Firehose_Button1_i(), _Firehose_Button2_i(),<br /> _Firehose_Button3_i()];<br /> return temp;<br />}<br />
  13. 13. Non Skinnable<br />Page 3 of 59<br />Flex 4 is full of new classes to learn. Let’s start by discussing an old favorite, UIComponent and a new addition Group.<br />UIComponent is still the base class of all components and containers in Flex 4. <br />Group is the base container class. It can hold an unknown number of elements which may be defined in MXML and is akin to a lighter-weight version of Container from the mx component set<br />
  14. 14. Skinnable*<br />Page 3 of 59<br />Two additional new classes in Flex 4 worth noting at this time: SkinnableComponent and SkinnableContainer<br />The SkinnableComponent class is the base class for all components where the view has been separated from component logic through the use of a skin. It is a UIComponent subclass<br />The SkinnableContainer class is a subclass of SkinnableComponent which allows for both a skin and unknown additional elements which may be defined in MXML<br />
  15. 15. mxmlContentFactory<br />Page 3 of 59<br />The goal of all of the work in the generated application code so far has been to set the mxmlContentFactory property of the Firehose class (Application subclass). <br />This property is defined in SkinnableContainer and allows us to specify those unknown MXML children. This property is typed as an IDeferredInstance.<br />this.mxmlContentFactory = <br /> new DeferredInstanceFromFunction(_Firehose_Array1_c); <br />
  16. 16. IDeferredInstance<br />Page 3 of 59<br />To be an IDeferredInstance a class must have a single method:<br />public function getInstance():Object {<br /> ...<br /> return something;<br />}<br />An IDeferredInstance defers the creation of an object until its getInstance() method is called. Each subsequent call returns the originally created instance<br />
  17. 17. DeferredInstanceFromFunction<br />Page 3 of 59<br />Our generated code is simply a function and the mxmlContentFactory expects the IDeferredInstance. The DeferredInstanceFromFunction handles this issue<br />this.mxmlContentFactory = <br /> new DeferredInstanceFromFunction(_Firehose_Array1_c); <br />The DeferredInstanceFromFunction class takes a function as its first parameter. When its getInstance() method is called it invokes that method to create the component graph<br />
  18. 18. Nested Controls<br />Page 3 of 59<br />The factory functions generated change a bit when we have nested controls:<br /><s:Button id="btn1" label="Click Me"/><br /><s:Group><br /> <s:Button id="btn2" label="Click You"/><br /> <s:Button id="btn3" label="Click It"/><br /></s:Group><br />
  19. 19. Nested Controls Generated<br />Page 3 of 59<br />private function _Firehose_Array1_c() : Array {<br />var temp : Array = [_Firehose_Button1_i(), _Firehose_Group1_c()];<br /> return temp;<br />}<br />private function _Firehose_Button1_i() : Button { ... }<br />private function _Firehose_Group1_c() : Group {<br />var temp : Group = Group();<br />temp.mxmlContent = [_Firehose_Button2_i(), _Firehose_Button3_i()];<br /> if (!temp.document) temp.document = this;<br /> return temp;<br />}<br />
  20. 20. Nested Group<br />Page 3 of 59<br />In the case of the nested group, you may notice that the mxmlContent property is set, instead of the mxmlContentFactory.<br />var temp : Group = Group();<br />temp.mxmlContent = [_Firehose_Button2_i(), _Firehose_Button3_i()];<br />Further, the property is set directly to the Array built by calling these methods. The mxmlContent property is the final home of all children. In this case they are created immediately instead of deferred<br />
  21. 21. Application Subclass<br />The next major piece of generated code is the SystemManager subclass. Several important things occur here:<br />The subclass implements IFlexModuleFactory<br />The subclass implements ISWFContext<br />The create() method is overridden<br />The info() method is overridden<br />Page 3 of 59<br />
  22. 22. IFlexModuleFactory<br />Page 3 of 59<br />The newly created SystemManager subclass will implement IFlexModuleFactory and ISWFContext which requires a number of interesting methods. The most interesting ones to us at this moment are:<br />function registerImplementation(interfaceName:String, impl:Object):void;<br />function getImplementation(interfaceName:String):Object;<br />function create(... parameters):Object;<br />function info():Object;<br />
  23. 23. registerImplementation()<br />Page 3 of 59<br />This method allows the Flex framework, and you should you wish, to register Singletons that implement a specific interface. It is sort of a Dependency Injection registration meets singleton and had a baby scenario:<br />public function registerImplementation(interfaceName:String,<br />impl:Object):void;<br />You call this method with an interface you wish to register and an implementing object. <br />
  24. 24. getImplementation()<br />Page 3 of 59<br />This method allows you to getImplementations that were previously registered. So, for example, if you wanted to register a given singleton you could then later retrieve it through the SystemManager<br />public function getImplementation(interfaceName:String):Object<br />
  25. 25. create()<br />Page 3 of 59<br />The create() method is where the magic happens and your app will be instantiated:<br />override public function create(... params):Object {<br /> ...<br />varmainClassName:String = <br />params.length == 0?"Firehose“:String(params[0]);<br />varmainClass:Class = Class(getDefinitionByName(mainClassName));<br /> if (!mainClass) return null;<br />varinstance:Object = new mainClass();<br /> if (instance is IFlexModule)<br /> (IFlexModule(instance)).moduleFactory = this;<br /> return instance;<br />}<br />
  26. 26. info()<br />Page 3 of 59<br />The info() method returns a generic object filled with required and optional properties used to configure the system. <br />Examples of data you may find in the object returned by info():<br /> RSL data, compiled locales, resource bundle names, application domain, main class name, mixins and the correct preloader to use<br />
  27. 27. info()<br />Page 3 of 59<br />In this code snippet from info() you can see where the mixins are specified. This is the way in which Flex applies some of the additional generated code to the system manager.<br />_info = {<br /> …<br />mainClassName: "Firehose",<br />mixins: [ "_Firehose_FlexInit", "_Firehose_Styles" ],<br />preloader: mx.preloaders.SparkDownloadProgressBar<br />}<br />
  28. 28. Mixin<br />Page 3 of 59<br />Mixin classes are decorated with the Mixin metadata and have a public static method named init() that takes a IFlexModuleFactory (SystemManager in this case) as an argument. <br />The mixin effectively sets properties and instances on the SystemManager to create the StyleManager, register styles and more<br />
  29. 29. Btn Binding Setup<br />Page 3 of 59<br />Earlier I mentioned that Flex creates a public var for btn on the host component because we have an MXML control named btn. That was true then.<br />However, this is Flex, and in Flex all MXML components are bindable, therefore, that public var actually becomes a getter and setter before we are done<br />
  30. 30. Btn Binding Setup<br />Page 3 of 59<br />[Bindable(event="propertyChange")]<br />public function get btn():spark.components.Button {<br /> return this._97884btn;<br />}<br />public function set btn(value:spark.components.Button):void{<br />varoldValue:Object = this._97884btn;<br /> if (oldValue !== value) {<br /> this._97884btn = value;<br /> if (this.hasEventListener("propertyChange"))<br />this.dispatchEvent( PropertyChangeEvent.createUpdateEvent(<br /> this, "btn", oldValue, value));<br /> }<br />}<br />
  31. 31. Watcher Setup<br />Page 3 of 59<br />If you add one Bindable properties to your application. You receive the following additons, which is the code watching for Bindable changes. <br /><?xml version="1.0" encoding="utf-8"?><br /><s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" <br />xmlns:s="library://ns.adobe.com/flex/spark"><br /> <fx:Script> <![CDATA[<br /> [Bindable]<br /> public varlblMe:String;<br /> ]]><br /> </fx:Script><br /> <s:Button id="btn" label="{lblMe}"/><br /></s:Application><br />
  32. 32. lblMe Binding Setup<br />Page 3 of 59<br />private function _Firehose_bindingsSetup():Array {<br />varresult:Array = [];<br /> result[0] = new mx.binding.Binding(this,<br /> null,<br /> null,<br /> "btn.label"<br /> , "lblMe");<br /> return result;<br />}<br />
  33. 33. lblMe Watcher Setup<br />Page 3 of 59<br />public function setup(target:Object,<br />propertyGetter:Function,<br />staticPropertyGetter:Function,<br />bindings:Array,<br />watchers:Array):void {<br /> watchers[0] = new mx.binding.PropertyWatcher("lblMe",<br /> {propertyChange: true },<br /> [bindings[0]],<br />propertyGetter );<br /> watchers[0].updateParent(target);<br />}<br /> }<br />}<br />
  34. 34. Application Constructor<br />Page 3 of 59<br />if (_watcherSetupUtil == null) {<br />varwatcherSetupUtilClass:Object = getDefinitionByName("_FirehoseWatcherSetupUtil");<br />watcherSetupUtilClass["init"](null);<br />}<br />_watcherSetupUtil.setup(this,<br />function(propertyName:String):* <br /> { return target[propertyName]; },<br />function(propertyName:String):* <br /> { return Firehose[propertyName]; },<br /> bindings, watchers);<br />mx_internal::_bindings = mx_internal::_bindings.concat(bindings);<br />mx_internal::_watchers = mx_internal::_watchers.concat(watchers);<br />for (var i:uint = 0; i < bindings.length; i++) {<br /> Binding(bindings[i]).execute();<br />}<br />
  35. 35. GAME TIME<br />Loading and Running<br />35<br />
  36. 36. SWF Load<br />Page 3 of 59<br />You begin loading your SWF into the browser of your choice. However, you need to remember that SWF is a streaming format, so it arrives a frame at a time.<br />Thanks to your frame metadata, you already told the SWF it should instantiate your SystemManager… so it does.<br />
  37. 37. SystemManager Constructor<br />Page 3 of 59<br />The SystemManager’s constructor is called where it does a few things like figure out if it is the top level or if it has been loaded into another SWF.<br />If it is the top, it sets alignments and scale modes on the stage and then does something extremely important:<br />stop();<br />We need to wait until we have loaded everything we need before we advance to the next frame and start the application<br />
  38. 38. SystemManager Constructor<br />Page 3 of 59<br />The final line in the SystemManager’s Constructor:<br />if (root && root.loaderInfo)<br />root.loaderInfo.addEventListener(Event.INIT, initHandler);<br />It waits until an INIT event is broadcast from the loaderInfo object. This event is broadcast the moment once everything needed by this first frame is available and the SystemManager’sConnstructor finishes<br />
  39. 39. init()<br />Page 3 of 59<br />One the initHandler() is called, the world gets more interesting. <br />This method does a little cleanup, removes the existing init event listener and some other pieces, however, the two critical things it does for this presentation:<br />Adds another event listener for a method named docFrameListener which is called when the rest of the application is loaded<br />Calls the initialize() method<br />
  40. 40. initialize()<br />Page 3 of 59<br />This method is responsible for creating the PreLoader. The PreLoader itself is a logical class, but it allows us to specify a display class which is displayed to the user to make a better user experience while we load the remainder of the app.<br />This method also starts downloading any RSLs needed for your application… and some it doesn’t need<br />Then we wait until the all of the RSLs are loaded and the remainder of the app is loaded<br />
  41. 41. kickOff()<br />Page 3 of 59<br />When both of these conditions are true (and they can happen in any order) either the preloader or the docFrameHandler catches this fact and ensures kickOff() is called.<br />This method registers a ton of classes as singletons to support everything from fonts to drag and drop.<br />It also instantiates all of those mixins we discussed in the pregame, adding those pieces to the system manager at this time<br />
  42. 42. initializeTopLevelWindow()<br />Page 3 of 59<br />This method does a lot of work to ensure we load correctly and size appropriately, however, the part that interests us most:<br />childManager.initializeTopLevelWindow(w, h);<br />ChildManager is an instance of a class that implements ISystemManagerChildManager, meaning that it has methods to handle the result of adding and removing children as well as the initialize method we call here.<br />In this case, it is an instance of ChildManager<br />
  43. 43. ChildManager()<br />Page 3 of 59<br />Inside of ChildManager, the create() method that was overridden by the compiler is called, effectively creating the instance of your application.<br />A creationComplete event handler is added to the application and the preloader is informed of the application’s existence so that it may leave gracefully when the application is ready<br />Note, the application is created but not yet added to the System Manager… that will happen much later<br />
  44. 44. ChildManager() cont<br />Page 3 of 59<br />Inside of the ChildManager, the addingChild() method is called.<br />This method sets the nestLevel for the new component (nestLevel increase as depth of the component increases)<br />The childAdded() method is called next, which dispatches an ADD event for the child and calls the child’s initialize…<br />And the fun begins<br />
  45. 45. PreInitialize<br />Page 3 of 59<br />The Application initializes several managers and the context menus before beginning the component initialization cycle.<br />This starts by broadcasting FlexEvent.PREINITIALIZE. This is one of the most important events in all of Flex. <br />It means the display object dispatching is initialized, however, it has yet to create any of its visual children. Anything that you want to do which will affect the number or type of children should be done NOW<br />
  46. 46. createChildren()<br />Page 3 of 59<br />Immediately after dispatching the event, the createChildren() method is called. The createChildren() method is responsible for creating all relatively static visual children of a component. <br />In non-skinnable components this method created all visual children directly. In skinnable components, this method invokes validateSkinChange() (which is invoked now and when the skin changes at runtime)<br />
  47. 47. validateSkinChange()<br />Page 3 of 59<br />The validateSkinChange() checks for an existing skin and detaches it if it exists. It then performs the most important operation here, it calls attachSkin()<br />..<br /> if (skin)<br />detachSkin();<br />attachSkin();<br />..<br />
  48. 48. attachSkin()<br />Page 3 of 59<br />The attachSkin() method finds the correct skin for this component, instantiates it, and passes the result to the setSkin() method.<br />In our application, this means creating an instance of the ApplicationSkin. ApplicationSkin is a Skin, which is just a Group and ultimately a UIComponent, so it will have this same life cycle recursively.<br />The setSkin() method sets the _skin property of the class and dispatches a skinChanged event<br />
  49. 49. attachSkin()<br />Page 3 of 59<br />At this point, the owner and hostComponent of the skin are set. The hostComponent of a skin always refers to the object for which it is providing a visual display.<br />Note, not the hostComponent and owner property is set after the class skin instantiated. You cannot access either of these properties during the skin’s construction<br />
  50. 50. attachSkin()<br />Page 3 of 59<br />After the skin is created, the styles of the component are passed to the skin for use.<br />At this point, the skin is added to the component, kicking off its life cycle. The addingChild() method is called, followed by actually adding it via the player APIs. Then the childAdded() method is called.<br />The childAdded method, much like it did for the application, causes the ApplicationSkin’s initialize method to be called<br />
  51. 51. Skin PreInitialize<br />Page 3 of 59<br />The skin now broadcasts its FlexEvent.PREINITIALIZE. <br />It means the skin is initialized, however, it has yet to create any of its visual children. <br />I reiterate, Anything that you want to do which will affect the number or type of children should be done NOW<br />
  52. 52. Skin createChildren()<br />Page 3 of 59<br />Immediately after dispatching the event, the createChildren() method is called. <br />Within the skin, the setMXMLContent method is called. This method takes an array of MXML objects defined in the skin (much like the array you saw in the nested example).<br />All old MXML elements are removed from the skin, and add all of the new elements, using a method named addElement()<br />
  53. 53. addElement()<br />Page 3 of 59<br />Immediately after dispatching the event, the createChildren() method is called. <br />Within the skin, the setMXMLContent method is called. This method takes an array of MXML objects defined in the skin (much like the array you saw in the nested example).<br />All old MXML elements are removed from the skin, and add all of the new elements. We use the word element here as the items we are adding or removing are of type IVisualElement<br />
  54. 54. IVisualElement<br />Page 3 of 59<br />IVisualElement is a new interface to spark which defines the properties that must be present on an object to be correctly sized, positioned and displayed in any type of spark container<br />In spark, controls, containers and even graphic primitives can be IVisualElements. Using this interface is a key component to allowing spark to intermingle these classes<br />
  55. 55. elementAdded() cont<br />Page 3 of 59<br />As the new visual elements are added to the skin, the skin’s elementAdded() method is called.<br />In this method, the elementAdded method of the layout object is also called to inform it of a change, and the invalidateLayering() method is called to inform the skin that the layering of objects may have changed. <br />This invalidation eventually leads to a call to assignDisplayObjects() which reorders the objects<br />
  56. 56. elementAdded()<br />Page 3 of 59<br />In the case where the element is an IGraphicalElement (an interface that descends from IVisualElement to specifically handle the needs of graphics) a special method called addingGraphicalElement() is called and passed the element.<br />IGraphicalElements are not displayObjects on their own like components. They are simply logic and state which draw onto a display object. This means that Flex must identify the correct display object for drawing.<br />
  57. 57. elementAdded()<br />Page 3 of 59<br />In all other cases, the element is assumed to be a displayObject and added to the display list via a method named addObjectToDisplayList()<br />This method ensures the child reaches the display list at the appropriate location<br />Any listeners are notified of the fact that a new element was added and the invalidateDisplayList() and invalidateSize() methods are called to ensure the skin is sized and repositioned<br />
  58. 58. More Recursion<br />Page 3 of 59<br />The addition of each of these elements to the display list causes their initialize() methods to be called.<br />They go through the same process of either instantiating components or instantiating skins, which then instantiate components, which may have skins, with components, with skins….<br />
  59. 59. Back Up<br />Page 3 of 59<br />Starting from the deepest point on the stack of children, each child does the following operations:<br />invalidateProperties()<br />invalidateSize()<br />invalidateDisplayList()<br />sets processedDescriptors = true<br />dispatches its FlexEvent.INITIALIZE event<br />
  60. 60. Child Additions<br />Page 3 of 59<br />Starting from the deepest point on the stack of children, each children performs the following operations:<br />invalidateProperties()<br />invalidateSize()<br />invalidateDisplayList()<br />sets processedDescriptors = true<br />dispatches its FlexEvent.INITIALIZE event<br />
  61. 61. FlexEvent.INITIALIZE<br />Page 3 of 59<br />The initialize event is always broadcast by the inner most child first.<br />It signifies that all of the visual children have been created, however, the children nor the component have been sized or positioned at this time.<br />This is a great place to make visual modifications to children.<br />
  62. 62. findSkinParts()<br />Page 3 of 59<br />After each skin initializes, you return to the attachSkin() method where the skin was first added.<br />We now execute a method named findSkinParts(). This method looks through the SkinParts defined via the [SkinPart] metadata in any SkinnableComponent subclass. <br />If it finds an element with a matching id in the skin, it provided the variable annotated with the [SkinPart] metadata with a reference to that part in the skin<br />
  63. 63. partAdded()<br />Page 3 of 59<br />As each of these parts is identified and the reference provided, the partAdded() method of SkinnableComponent is called and provided both the string name of the skin part and a reference to it:<br />if (this[id] != null && !(this[id] is IFactory))<br />partAdded(id, this[id]);<br />It is common to override this method in your own components to configure each skin part as it is added. There is a parallel method called partRemoved() which is called with the same arguments if a part is removed.<br />
  64. 64. partAdded()<br />Page 3 of 59<br />The default behavior of the partAdded() method is to dispatch a SkinPartEvent.PART_ADDED event with the partName and instance which can also be used for configuration or other logic<br />
  65. 65. SkinStates<br />Page 3 of 59<br />After all parts are added, the invalidateSkinState() method is called.<br />When you define a SkinnableComponent, you can specify required SkinStates that the skin must fulfill. Meaning it will have those states defined in the skin.<br />[SkinState("up")]<br />[SkinState("over")]<br />--- --- --- --- --- ---<br /><s:states><br /> <s:State name="up" /><br /> <s:State name="over" /><br /></s:states><br />
  66. 66. SkinStates<br />Page 3 of 59<br />The invalidateSkinState() method informs the component that the skin needs to know its new visual state<br />As a result of this call, the getCurrentSkinState() method of this component will be called asynchronously. It is expected to return a string that matches one of those valid states<br />It can derive this information in any way it chooses and is not bound to the component state<br />
  67. 67. Deferred<br />Page 3 of 59<br />After all of the skins are attached, the stack returns to the createChildren() method<br />Here it calls a method named createDeferredContentIfNeeded()<br />This method looks for any items specified in the mxmlContentFactory that have not yet been instantiated and creates them now… starting yet another recursive cycle. Note, this is where the Flex compiler assigned our original content<br />
  68. 68. Deferred Creation<br />Page 3 of 59<br />This means initialize is a bit trickier.<br />Skins for a class are created before MXML content, so for instance the ApplicationSkin will be created well before the Button creation begins<br />This is consistent with the use of initialize but, depending on the complexity of the skin may seem strange at first glance<br />
  69. 69. Recursion Complete<br />Page 3 of 59<br />One all of the children are initialized from the inner most to the outer, you will be able to finish the initialize() method of the Application that we started many slides ago.<br />Now we need to worry about invalidation.<br />
  70. 70. Invalidation<br />Page 3 of 59<br />All of this invalidation effectively adds each of these components to a priority queue. This priority queue sorts based on the nestLevel that we mentioned earlier.<br />As these queues are resolved the outer most item toward the deepest have their validateProperties() method called.<br />Then the deepest moving toward the outermost have their validateSize() method called.<br />Finally, from the outer toward deepest, the validateDisplayList() method is called<br />
  71. 71. Invalidation<br />Page 3 of 59<br />After each component has had a chance to complete all necessary validation, it is marked as initialized. Not this is different than the INITIALIZE event<br />Marking a component as Initialized does two important things. <br />it sets the component to visible (if applicable)<br />It dispatches a FlexEvent.CREATION_COMPLETE<br />
  72. 72. creationComplete<br />Page 3 of 59<br />The FlexEvent.CREATION_COMPLETE means that all layout, sizing and positioning is complete and the item can now be visible on the screen.<br />It is just about the worst time to do anything, save for operations that need to know the size and position of a child<br />
  73. 73. Application Visible<br />Page 3 of 59<br />Once all of the children have broadcast their creationComplete event, the time for the application to complete is here<br />The application broadcasts its creationComplete, which is a trigger to System Manager.<br />The System Manager destroys the preloader and adds the Application as a child to the System Manager, making it visible.<br />
  74. 74. Application Complete<br />Page 3 of 59<br />The act of making the application a child of the system manager is among the last acts performed before the System Manager broadcasts a FlexEvent.APPLICATION_COMPLETE from the Application.<br />This signals that the application is ready to be used.<br />
  75. 75. Questions<br />Page 3 of 59<br />?<br />
  76. 76. Page 59 of 59<br />Me<br />Michael Labriola<br />http://twitter.com/mlabriola<br />
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×