初始順序以下:編程
- preloader -> systemManager -> FlexApplication started ...
- preinitialize 在全部的初始化以前觸發,沒有子組件的定義,可是能夠引用組件的變量.
- initialize 當全部子組件生成完成後觸發,在這個時間點尚未組件被渲染出來.
- creationComplete 組件定義完成並已經在顯示列表.
- applicationComplete 全部的組件初始化完成並顯示.
首先介紹一下SystemManager. SystemManager是Flex應用的主控者, 它控制着應用窗口, Application實例, 彈出窗口, cursors, 並管理着ApplicationDomain中的類. SystemManager是FlashPlayer實例化的第一個類, 它存儲了主應用窗口的大小和位置信息, 保存其子組件好比:浮動彈出窗口和模態窗口的痕跡. 經過SystemManager能夠得到內嵌字體,樣式和document對象.
自定義的可視化組件(UIComponent的子類)只有在調用過addChild()後, 纔會有一個SystemManager賦給他們, 以前是Null. 因此在自定義可視化組件的構造函數中不要使用SystemManager.
一般, Application對象建立時, 發生以下事件:
1. 實例化Application對象
2. 初始化Application.systemManager
3. Application在初始化過程以前, 派發預初始化事件.
4. 調用createChild(). 此時, 全部應用組件被建立, 全部組件的createChild()被調用.
5. Application派發初始化事件, 代表全部的組件初始化完畢.
6. 派發creationComplete事件
7. Application對象添加到顯示列表中
8. 派發applicationComplete事件
大 多數狀況下, 咱們使用<mx:Application>來建立application對象, 但若是使用ActionScript來建立的話, 那麼建議不要在application的構造函數中建立組件, 推薦在crateChildren函數中, 主要是從性能方面考慮.
Flash包含的是一個時間線上的多個幀, 而Flex的SWF只包含2個幀. SystemManager, Preloader, DownloadProgressBar和少許工具類都在第一幀, 剩下的包括應用代碼/ 內嵌資源全都在第二幀中. 當Flash Player下載下載SWF時, 只要接收到第一幀內足夠的數據, 就會實例化SystemManager, 由它來建立Preloader, 而後建立DownloadProgressBar, 這兩個對象會察看剩餘字節的傳輸過程. 當第一幀的全部字節傳輸完畢後, SystemManager發送enterFrame到第二幀, 而後是其餘事件. 最後Application對象派發applicationComplete事件.
Flex 是一個事件驅動的編程模型, 任何事情的發生, 其背後必然存在一個事件. 而開發者第一次看到MXML時, 很難體會到一個Xml標記的應用的事件流和實例化的生命週期. 這個對於HTML和Flash的開發者尤爲會感到困惑, 由於其熟悉的方式與Flex的一點也不類似. HTML的實例化是從上到下的, Flash的執行是從Frame0開始一幀幀運行的. 而Flex則又有不一樣.
從咱們開始學習Flex時, 咱們就須要瞭解事件流和MXML的實例化. 我很是困惑由於我實在難以理解什麼樣的事件會被觸發或者事件何時會被觸發. 關鍵是要理解事件的基礎並親自觀察事件流的初始化.
咱們來看一個簡單的MXML的應用.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundGradientColors="[#67cbff, #fcffff]" color="#000000" fontSize="12" preinitialize="report( event , 'preinitialize' )" initialize="report( event , 'initialize' )" creationComplete="report( event , 'creationComplete' )" applicationComplete="report( event , 'applicationComplete' )" > <mx:Script> <![CDATA[ [Bindable] public var outTextData:String=""; public function report( event:Event , value:String ):void Unknown macro: { outTextData += String( flash.utils.getTimer() ) + 'ms >> ' + event.currentTarget + '.' + value + 'n'; } ]]> </mx:Script> <mx:TextArea id="outTextArea" text=" Unknown macro: { outTextData } " right="10" left="10" top="50" bottom="10" alpha="0.5" wordWrap="false" initialize="report( event , 'initialize' )" creationComplete="report( event , 'creationComplete' )" /> <mx:Button y="10" height="30" left="168" width="150" id="HelloButton" label="Say Hello" initialize="report( event , 'initialize' )" creationComplete="report( event , 'creationComplete' )" rollOver="report( event , 'rollOver' )" rollOut="report( event , 'rollOut' )" click="report( event , 'click > Hello!' )" /> <mx:Button id="GoodByeButton" label="Say Goodbye" y="10" left="10" height="30" width="150" color="#000000" initialize="report( event , 'initialize' )" creationComplete="report( event , 'creationComplete' )" click="report( event , 'click > Goodbye!' )" /> <mx:Button id="ClearButton" label="Clear" y="10" left="326" height="30" color="#000000" right="10" initialize="report( event , 'initialize' )" creationComplete="report( event , 'creationComplete' )" click="outTextData='';report( event , 'click' )" /> </mx:Application>
這個應用運行時, 輸出了實例流程和事件流. 這校咱們就可以看到全部事件的觸發順序. 能夠發現應用啓動後, 事件的順序是必定的. 下面是輸出的內容:
167ms >> EventFlow0.preinitialize
183ms >> EventFlow0.outTextArea.initialize
187ms >> EventFlow0.HelloButton.initialize
188ms >> EventFlow0.GoodByeButton.initialize
189ms >> EventFlow0.ClearButton.initialize
189ms >> EventFlow0.initialize
243ms >> EventFlow0.outTextArea.creationComplete
243ms >> EventFlow0.HelloButton.creationComplete
243ms >> EventFlow0.GoodByeButton.creationComplete
244ms >> EventFlow0.ClearButton.creationComplete
244ms >> EventFlow0.creationComplete
246ms >> EventFlow0.applicationComplete
一旦applicationComplete事件觸發後, 組件就會在鼠標事件派發後觸發本身的事件.
1807ms >> EventFlow0.HelloButton.rollOver
2596ms >> EventFlow0.HelloButton.rollOut
2954ms >> EventFlow0.HelloButton.rollOver
3170ms >> EventFlow0.HelloButton.rollOut
3543ms >> EventFlow0.HelloButton.rollOver
4052ms >> EventFlow0.HelloButton.click > Hello!
4267ms >> EventFlow0.HelloButton.click > Hello!
4474ms >> EventFlow0.HelloButton.click > Hello!
4569ms >> EventFlow0.HelloButton.rollOut
4907ms >> EventFlow0.GoodByeButton.click > Goodbye!
5130ms >> EventFlow0.GoodByeButton.click > Goodbye!
關於creationComplete事件的發生時機,手冊中是這樣說的:
假設程序中有這樣的結構:
Application
OuterVBox
InnerVBox1
InnerVBoxLabel1
InnerVBox2
InnerVBoxLabel2
事件:preinitialize, initialize, creationComplete發生的順序是這樣的:
OuterVBox preinitialize
InnerVBox1 preinitialize
InnerVBox1Label preinitialize
InnerVBox1Label initialize
InnerVBox1 initialize
InnerVBox2 preinitialize
InnerVBox2Label preinitialize
InnerVBox2Label initialize
InnerVBox2 initialize
OuterVBox initialize
InnerBox1Label creationComplete
InnerVBox2Label creationComplete
InnerVBox1 creationComplete
InnerVBox2 creationComplete
OuterVBox creationComplete
全部的initialization事件完成後,creationComplete時間纔開始發生,先從葉子控件開始,而後是他們的父控件,直到application。
若是將 OuterVBox容器變成ViewStack而且creationPolicy 屬性爲auto, 則事件發生順序是:
OuterViewStack preinitialize
InnerVBox1 preinitialize
InnerVBox2 preinitialize
OuterViewStack initialize
InnerBox1Label preinitialize
InnerBox1Label initialize
InnerVBox1 initialize
InnerBox1Label creationComplete
InnerVBox1 creationComplete
OuterViewStack creationComplete
然而,對於item renderer 或者 item editor, Flex 可能會重用item renderer 或者item editor的實例。可是被重用的renderer 或者item editor的實例不會再次發生creationComplete事件。做爲替代,你可使用dataChange事件。Flex 會在每次data屬性發生變化時觸發dataChange事件。在Accessing the listData property(Flex2 help中)一節中的例子就使用了dataChange事件來更新在DataGrid控件的item renderer中的TextArea的內容。