Flex Application 初始化順序

原文地址: [url]http://www.jexchen.com[/url]

大家都知道,我們在編寫Flex應用程序時,通常是以<mx:Application>標籤作爲開頭,實際上,Flex應用程序在啓動運行的時候並不是直接從Application開始運行,在這之前還有一部分悄悄的先運行了,正如大家所看到的,當我們運行編寫好的Flex應用程序時,儘管我們沒有編寫任何與啓動進度載入條相關的代碼,但無一例外的,應用程序均會爲我們自動加上這一部分。因此纔有我們看到的如下圖所示的標準的Flex loading載入條。

通常我們所說的Flex應用程序,本質上來說是基於Flex框架、採用ActionScript 3.0編寫的Flash應用程序,從這一點來說,它和普通的Flash應用程序沒有任何差別。相對來說,傳統的使用Flash IDE(如Flash CS3)創建Flash程序時更多的基於“時間線”(Timeline)及“幀”(Frame)的概念,更易於設計師理解;而基於Flex框架來創建的 Flash應用程序更多是強調程序性,很少提及“時間線”與“幀”的概念,更易於程序員理解。其實Flex應用程序一樣也有時間線,只是這部分由Flex 框架隱藏起來了,通常不爲大家所熟悉,在默認創建Flex程序時,這一切Flex已幫我們完成了,但瞭解這部分內容更有助於大家對Flex應用程序的啓動有更深刻的認識,以便能對程序更靈活的控制與發揮~~


我們來看看上面這幅示意圖,Flex應用程序共由兩幀組成,第1幀爲preloader部分,第2幀爲主應用程序部分,此兩部分由Flex應用程序的根SystemManager統管,SystemManager是flash.display.MovieClip的子類,影片剪輯(movie clip)支持幀。由於swf屬於一種漸進式(progressive)下載的格式,正是由於swf格式這個特性,Flash Player並不需要等待整個程序下載完成便可直接訪問已載入幀的內容,因此第一幀通常用來作爲應用程序載入時的loading畫面顯示,一般來說,第一幀包含的內容應該儘可能的少(在第一幀中儘量不要含有Flex框架的組件),以便能很快的下載並立即顯示;第二幀纔是主應用程序真正的內容,一旦 SystemManager實例進入到第二幀後,即開始內部主應用程序運行的生命週期(life cycle),也就是進入我們最爲熟悉的<mx:Application>運行的部分(SystemManger實例有一 application的屬性,在第1幀時,此屬性爲null,當進入到第2幀時,該屬性才指向真正的主程序application實例)記住我們開始所說的,Flex應用程序總的來說是以事件驅動的程序。

在程序進入第2幀,主程序application開始運行後,便會相應的觸發相應的一系列事件,按事件發生的先後順序依次來介紹:

preinitialize

應用程序application已實例化,但此時還未創建任何相關的孩子組件(child component)

initialize

此時,創建了相應的孩子組件,但還未對這些子組件進行佈局

creationComplete

應用程序application完成全部實例化,並完成所有子組件的佈局

apllicationComplete

上面三處事件的完成,表明application內部啓動的整個進程完成,接下來便會通知SystemManager派發applicationComplete事件。此時,啓動程序啓動完成並準備運行。


Flash包含的是一個時間線上的多個幀, 而Flex的SWF只包含2個幀. SystemManager, Preloader, DownloadProgressBar和少量工具類都在第一幀, 剩下的包括應用代碼/ 內嵌資源全都在第二幀中. 當Flash Player下載下載SWF時, 只要接收到第一幀內足夠的數據, 就會實例化SystemManager, 由它來創建Preloader, 然後創建DownloadProgressBar, 這兩個對象會察看剩餘字節的傳輸過程. 當第一幀的所有字節傳輸完畢後, SystemManager發送enterFrame到第二幀, 然後是其他事件. 最後Application對象派發applicationComplete事件.
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函數中, 主要是從性能方面考慮.
Flex 是一個事件驅動的編程模型, 任何事情的發生, 其背後必然存在一個事件. 而開發者第一次看到MXML時, 很難體會到一個Xml標記的應用的事件流和實例化的生命週期. 這個對於HTML和Flash的開發者尤其會感到困惑, 因爲其熟悉的方式與Flex的一點也不相似. HTML的實例化是從上到下的, Flash的執行是從Frame0開始一幀幀運行的. 而Flex則又有不同.

我們來看一個簡單的MXML的應用.

 1. <?xml version="1.0" encoding="utf-8"?> 
2. <mx:Application
3. xmlns:mx="http://www.adobe.com/2006/mxml"
4. layout="absolute"
5. backgroundGradientColors="[#67cbff, #fcffff]"
6. color="#000000"
7. fontSize="12"
8. preinitialize="report( event , 'preinitialize' )"
9. initialize="report( event , 'initialize' )"
10. creationComplete="report( event , 'creationComplete' )"
11. applicationComplete="report( event , 'applicationComplete' )"
12. >
13.
14. <mx:Script>
15. <![CDATA[
16.
17. [Bindable]
18.
19. public var outTextData:String="";
20.
21. public function report( event:Event , value:String ):void
22. {
23. outTextData += String( flash.utils.getTimer() ) + 'ms >> '
24. + event.currentTarget + '.' + value + '\n';
25. }
26.
27. ]]>
28. </mx:Script>
29.
30. <mx:TextArea
31. id="outTextArea"
32. text="{ outTextData }"
33. right="10" left="10" top="50" bottom="10" alpha="0.5"
34. wordWrap="false"
35. initialize="report( event , 'initialize' )"
36. creationComplete="report( event , 'creationComplete' )"
37. />
38.
39. <mx:Button
40. y="10" height="30" left="168" width="150"
41. id="HelloButton"
42. label="Say Hello"
43. initialize="report( event , 'initialize' )"
44. creationComplete="report( event , 'creationComplete' )"
45. rollOver="report( event , 'rollOver' )"
46. rollOut="report( event , 'rollOut' )"
47. click="report( event , 'click > Hello!' )"
48. />
49.
50. <mx:Button
51. id="GoodByeButton"
52. label="Say Goodbye"
53. y="10" left="10" height="30" width="150" color="#000000"
54. initialize="report( event , 'initialize' )"
55. creationComplete="report( event , 'creationComplete' )"
56. click="report( event , 'click > Goodbye!' )"
57. />
58.
59. <mx:Button
60. id="ClearButton"
61. label="Clear"
62. y="10" left="326" height="30" color="#000000" right="10"
63. initialize="report( event , 'initialize' )"
64. creationComplete="report( event , 'creationComplete' )"
65. click="outTextData='';report( event , 'click' )"
66. />
67.
68. </mx:Application>


這個應用運行時, 輸出了實例流程和事件流. 這校我們就能夠看到所有事件的觸發順序. 可以發現應用啓動後, 事件的順序是一定的. 下面是輸出的內容:

1. 167ms >> EventFlow0.preinitialize
2. 183ms >> EventFlow0.outTextArea.initialize
3. 187ms >> EventFlow0.HelloButton.initialize
4. 188ms >> EventFlow0.GoodByeButton.initialize
5. 189ms >> EventFlow0.ClearButton.initialize
6. 189ms >> EventFlow0.initialize
7. 243ms >> EventFlow0.outTextArea.creationComplete
8. 243ms >> EventFlow0.HelloButton.creationComplete
9. 243ms >> EventFlow0.GoodByeButton.creationComplete
10. 244ms >> EventFlow0.ClearButton.creationComplete
11. 244ms >> EventFlow0.creationComplete
12. 246ms >> EventFlow0.applicationComplete
13. 一旦applicationComplete事件觸發後, 組件就會在鼠標事件派發後觸發自己的事件.
14. 1807ms >> EventFlow0.HelloButton.rollOver
15. 2596ms >> EventFlow0.HelloButton.rollOut
發佈了15 篇原創文章 · 獲贊 0 · 訪問量 2631
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章