天天看點

Flex 頁面 初始化順序

Flex RemoteObject 遠端調用對像預設是異步執行的,就像AJAX那樣,,,,這樣子有時候對于等待業務層反回值是很不友善,,是以在Flex RemoteObject 對像中也有設定為同步執行的方法:

兩種解決辦法: 1,相關處理代碼放在result傳回那個方法裡面. 2,concurrency 設定為single或last. (<mx:RemoteObject concurrency="single"/> concurrency的屬性就是同步和異步的 預設的是multiple)

<wbr><a target="_blank" id="cb_post_title_url" class="postTitle2" href="http://www.cnblogs.com/ddw1997/archive/2012/10/11/2719746.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >Flex中實作Application未初始化前加載配置内容</a></wbr>

http://www.cnblogs.com/ddw1997/archive/2012/10/11/2719746.html

flex元件在建立的時候都會經曆四個事件:preinitialize,initialize,creationComplete和updateComplete(updateComplete事件在任何改動視覺的情況下都會發生,不是初始化時獨有的)。我這裡有個例子來檢測在嵌套和平行的情況下,測試各個元件的事件抛出順序。

[c-sharp] view plain copy print ?

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <mx:Applicationxmlns:mx="http://www.adobe.com/2006/mxml"layout="absolute"
  3. preinitialize="showEvent(event)"
  4. initialize="showEvent(event)"
  5. creationComplete="showEvent(event)"
  6. updateComplete="showEvent(event)">
  7. <mx:Script>
  8. <!--[CDATA[
  9. importflash.utils.getTimer;
  10. privatefunctionshowEvent(event:Event):void
  11. {
  12. trace(flash.utils.getTimer().toString()+">>"
  13. +event.currentTarget.name+""+event.type);
  14. }
  15. ]]-->
  16. </mx:Script>
  17. <mx:Canvasid="canv1"
  18. preinitialize="showEvent(event)"
  19. initialize="showEvent(event)"
  20. creationComplete="showEvent(event)"
  21. updateComplete="showEvent(event)">
  22. <mx:Buttonid="btn1"
  23. preinitialize="showEvent(event)"
  24. initialize="showEvent(event)"
  25. creationComplete="showEvent(event)"
  26. updateComplete="showEvent(event)"/>
  27. </mx:Canvas>
  28. <mx:Buttonid="btn2"
  29. preinitialize="showEvent(event)"
  30. initialize="showEvent(event)"
  31. creationComplete="showEvent(event)"
  32. updateComplete="showEvent(event)"/>
  33. </mx:Application>

<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" preinitialize="showEvent(event)" initialize="showEvent(event)" creationComplete="showEvent(event)" updateComplete="showEvent(event)"> <mx:Script> <!--[CDATA[ import flash.utils.getTimer; private function showEvent(event:Event):void { trace(flash.utils.getTimer().toString()+" >> " +event.currentTarget.name+" "+event.type); } ]]--> </mx:Script> <mx:Canvas id="canv1" preinitialize="showEvent(event)" initialize="showEvent(event)" creationComplete="showEvent(event)" updateComplete="showEvent(event)"> <mx:Button id="btn1" preinitialize="showEvent(event)" initialize="showEvent(event)" creationComplete="showEvent(event)" updateComplete="showEvent(event)"/> </mx:Canvas> <mx:Button id="btn2" preinitialize="showEvent(event)" initialize="showEvent(event)" creationComplete="showEvent(event)" updateComplete="showEvent(event)"/> </mx:Application>

輸出:

[c-sharp] view plain copy print ?

  1. 349>>InitExample0preinitialize
  2. 356>>canv1preinitialize
  3. 359>>btn1preinitialize
  4. 369>>btn1initialize
  5. 370>>canv1initialize
  6. 371>>btn2preinitialize
  7. 372>>btn2initialize
  8. 372>>InitExample0initialize
  9. 476>>btn1creationComplete
  10. 477>>btn1updateComplete
  11. 477>>canv1creationComplete
  12. 477>>canv1updateComplete
  13. 477>>btn2creationComplete
  14. 477>>btn2updateComplete
  15. 478>>InitExample0creationComplete
  16. 481>>InitExample0updateComplete

349 >> InitExample0 preinitialize 356 >> canv1 preinitialize 359 >> btn1 preinitialize 369 >> btn1 initialize 370 >> canv1 initialize 371 >> btn2 preinitialize 372 >> btn2 initialize 372 >> InitExample0 initialize 476 >> btn1 creationComplete 477 >> btn1 updateComplete 477 >> canv1 creationComplete 477 >> canv1 updateComplete 477 >> btn2 creationComplete 477 >> btn2 updateComplete 478 >> InitExample0 creationComplete 481 >> InitExample0 updateComplete

結論:

就單個元件而言,事件的抛出順序是preinitialize,initialize,creationComplete

嵌套關系的兩個元件(比如Canvas和button1),preinitialize先外後内,initialize和creationComplete先内後外。隻是creationComplete要在下一次update才會發生。 平行關系的兩個元件(比如Canvas和button2),按mxml内的順序,隻有前面元件initialize結束後,後面的元件才會抛出preinitialize。

如果不了解 Flex 釋出的 swf 結構和初始化流程,會在工作中遇到困難, Flex 釋出的 swf 結構和 Flex 對顯示層級的劃分是 Flex 架構中的一部分。

Flex釋出的swf結構

Flex生成的swf是個2幀的MovieClip,文檔類繼承SystemManager,主時間軸上沒有任何内容,幀上也沒有代碼,2幀結構是為建立加載應用程式的預設加載器,這種早期就開始使用的加載方式在如今仍然具有優勢,預設的加載器如圖:

Flex 頁面 初始化順序

加載器的外觀是通過代碼繪制的,SystemManager使用工廠模式來建立應用程式,這使得第一幀涉及的Flex底層較少,加載器在漸進式下載下傳過程中會很快的顯示在舞台上,當Flex工程和需要的共享庫下載下傳完畢後,SystemManager跳到第二幀,從應用程式域中找出Application的定義建立執行個體。下圖為swf初始化的順序:

Flex 頁面 初始化順序

SystemManager

SystemManager是Flex釋出swf的文檔類,是應用程式的入口,SystemManager繼承MovieClip,不僅控制swf的加載和啟動,還劃分Flex工程顯示層級,儲存嵌入字型和樣式,監視swf畫布大小等頂級功能,某些功能被映射到Application或全局管理器中,你可以選擇通路的方式。

Flex顯示層級劃分

SystemManager對Flex應用程式的顯示層級劃分如下:

Flex 頁面 初始化順序

SystemManager是頂級顯示層的管理器,凡是父級為SystemManager的顯示層都是頂級顯示層,應用程式、彈出視窗、工具提示、滑鼠光标都是父級為SystemManager的頂級層,popUpChildren:IChildList,toolTipChildren:IChildList,cursorChildren:IChildList并不是具體的顯示層,而是記錄頂級層的集合,SystemManager自動維護這些集合,使得彈出視窗總是位于應用程式之上,工具提示總是位于彈出視窗之上,滑鼠光标總是位于工具提示之上。彈出視窗、工具提示、滑鼠光标集合由Flex架構在運作中添加和删除内容,不要通手動修改這些集合以幹擾架構運作,但内可以添加應用程式層對你的項目進行劃分。

SystemManager重寫了DisplayObjectContainer的接口,它與Container一樣忽略輔助性的元素,通過SystemManager擷取的子級實際上不包含浮動視窗、工具提示和光标這樣的輔助層,也不包括内部的滑鼠捕捉層,隻包含預設的應用程式層和使用addChild()等方法添加進來的應用層,這也是SystemManager提供cursorChildren等這樣的集合通路而不是通過getChildAt()通路頂級顯示層的原因。通過cursorChildren這樣的集合也并不能完全暴露SystemManager的所有子級,要通路原始子級,可以使用rawChildren:IChildList屬性進行周遊,但不要通過此手段破壞SystemManager的結構。

載入Flex項目

SystemManager實作IFlexModuleFactory接口,但并不表示它可以作為一個Module載入,擴充IFlexModuleFactory是為了利用工廠模式分離preloader和Application的關聯。整個Flex項目确實可以載入到其它項目中的,但不是以Module方式載入而是通過普通方法加載,例如使用SWFLoader或Loader加載,SystemManager作為頂級容器加入到項目的顯示清單。

SystemManager的application:IUIComponent屬性引用載入Flex項目的application執行個體,getDefinitionByName(name:String):Object方法擷取載入swf中的定義,例如Object(SystemManager(mySwfLoader.content).application.testButton擷取載入項目中的testButton按鈕執行個體,SystemManager(mySwfLoader.content).getDefinitionByName("TestButton")擷取載入項目中的TestButtond定義。

将Flex項目載入到另一個Flex項目中後,會使用新項目的SystemManager管理頂級層,因為全局管理器隻能有一個,例如載入項目中有彈出視窗,這個彈出視窗的父級為新項目的SystemManager,原項目的SystemManager僅作為一個父級存在,它的功能隻限定于引用,原項目中可以使用topLevelSystemManager:ISystemManager屬性引用新項目的SystemManager。讓一個Flex項目載入另外一個Flex項目沒有什麼優勢,不能很好的展現項目和子產品的關系,代碼組織不明确且無法避免重定義,我們應該使用Module來分割應用程式。一個例外是你可以讓Flash項目載入Flex工程建構UI來代替Flash的v3元件架構,但你需要斟酌加載swf給Flash項目帶來的等待時間,Flex項目通常體積比較大。

Application

Application是應用層的頂級容器,Application的某些屬性關系到Flex如何編譯項目或生成的網頁,這些屬性不能用as設定,隻能通過mxml标簽設定,如下:

屬性 說明
frameRate:Number 項目幀數,預設為24幀
pageTitle:String 浏覽器标題欄中顯示的文本
usePreLoader:Boolean 是否顯示預加載器PreLoader
preloader:Object 預加載器類路徑
scriptRecursionLimit:int 最大堆棧
scriptTimeLimit:Number 最大失去響應時間

擷取swf位址和flashVars

Application的url:String可以擷取swf位址,但這個屬性依然不能擷取網頁傳遞的值對,因為Application是通過釋出swf的loaderInfo擷取位址,parameters:Object屬性映射了loadInfo的flashVars,通路flashVars參數比較友善。

初始化流程

Application和UIComponent的初始化過程涉及到很多方面,若揉雜在一起便會對維護和修改造成混亂的局面,于是Flex将初始化過程進行階段劃分并制定執行順序,每個階段完成都會觸發一個事件,這些事件不僅能夠反映初始化過程,還為我們提供了對初始化進行增補的手段。

UIComponent初始化流程

Flex元件和Flex容器都繼承UIComponent,它們的初始化流程都被定義在UIComponent中,這表示Flex元件和Flex容器的初始化流程是相同的,Flex元件雖然不能象容器那樣添加子級,但不代表它們沒有子級,如Button内部包含的UITextField,某些Flex元件和Flex容器一樣包括其它Flex元件,如Combox的子級包括List元件,這樣的元件稱為複合元件。Flex元件和Flex容器均采取遞歸的方式初始化,即先完成子級初始化,然後完成父級初始化,在初始化過程中伴随者事件,如圖:

Flex 頁面 初始化順序

在UIComponent的構造函數中不會建立元件的子級,構造函數中隻對元件的預設屬性、樣式進行設定,并且為元件添加偵聽器,子級是在initilize()方法中建立的,initilize()方法是UIcomponent初始化核心,它不由構造函數調用的,而是調用addChild()和addChildAt()方法時執行,好處是節省記憶體占用,初始化後的元件必然要占據大量的記憶體,動态添加的子級在加入容器之前保持其最小體積,直到加入容器時才具有正常的記憶體占用。在createChildren()方法中建立元件的子級,如果子級也是UIComponent,則會産生遞歸,preInitilize事件提供建立子級之前的準備工作,childrenCreated()和initilizationComplete()方法提供子級建立完畢之後的改造工作,差別是它們之間相隔一個initializeAccessibility()方法,initializeAccessibility()用于初始化輔助功能,當所有子級以及遞歸完成後,發送initilize事件,如果UIComponent是容器,則接着對元件進行布局,布局完成後發送creationComplete事件。了解initilize()方法工作原理對開發自定義元件非常重要,選擇繼承UIComponent時,應該把建立子級的代碼放入createchildren()方法中;選擇繼承内置元件時,可以在childrenCreated()或initilizationComplete()方法中對元件進行改造;如果隻需要對元件的屬性或者樣式進行設定,可以選擇preInitilize、initilize、事件在不同階段進行設定,要修改布局,可在creationComplete事件後進行。

Application初始化流程

Application的初始化過程不但包括内部子級的初始化,還通知SystemManager将其加入舞台的顯示清單,Application是Flex容器,它的初始化規則遵守普通元件的規則,這裡以事件為主線闡明Application在初始化過程中經曆的階段:

Flex 頁面 初始化順序

Application擁有普通容器沒有的ApplicationComplete事件,Application被SystemManager添加到顯示清單後觸發,完成度比createComplete更高,在這個事件中可以通路舞台。

初始化事件

初始化事件都是FlexEvent事件,對應類型如下表:

事件名稱 事件類型
preinitilize FlexEvent.PREINITIALIZE
initilize FlexEvent.INITIALIZE
creationComplete FlexEvent.CREATION_COMPLETE
applicationComplete FlexEvent.APPLICATION_COMPLETE

如果不了解 Flex 釋出的 swf 結構和初始化流程,會在工作中遇到困難, Flex 釋出的 swf 結構和 Flex 對顯示層級的劃分是 Flex 架構中的一部分。

Flex釋出的swf結構

Flex生成的swf是個2幀的MovieClip,文檔類繼承SystemManager,主時間軸上沒有任何内容,幀上也沒有代碼,2幀結構是為建立加載應用程式的預設加載器,這種早期就開始使用的加載方式在如今仍然具有優勢,預設的加載器如圖:

Flex 頁面 初始化順序

加載器的外觀是通過代碼繪制的,SystemManager使用工廠模式來建立應用程式,這使得第一幀涉及的Flex底層較少,加載器在漸進式下載下傳過程中會很快的顯示在舞台上,當Flex工程和需要的共享庫下載下傳完畢後,SystemManager跳到第二幀,從應用程式域中找出Application的定義建立執行個體。下圖為swf初始化的順序:

Flex 頁面 初始化順序

SystemManager

SystemManager是Flex釋出swf的文檔類,是應用程式的入口,SystemManager繼承MovieClip,不僅控制swf的加載和啟動,還劃分Flex工程顯示層級,儲存嵌入字型和樣式,監視swf畫布大小等頂級功能,某些功能被映射到Application或全局管理器中,你可以選擇通路的方式。

Flex顯示層級劃分

SystemManager對Flex應用程式的顯示層級劃分如下:

Flex 頁面 初始化順序

SystemManager是頂級顯示層的管理器,凡是父級為SystemManager的顯示層都是頂級顯示層,應用程式、彈出視窗、工具提示、滑鼠光标都是父級為SystemManager的頂級層,popUpChildren:IChildList,toolTipChildren:IChildList,cursorChildren:IChildList并不是具體的顯示層,而是記錄頂級層的集合,SystemManager自動維護這些集合,使得彈出視窗總是位于應用程式之上,工具提示總是位于彈出視窗之上,滑鼠光标總是位于工具提示之上。彈出視窗、工具提示、滑鼠光标集合由Flex架構在運作中添加和删除内容,不要通手動修改這些集合以幹擾架構運作,但内可以添加應用程式層對你的項目進行劃分。

SystemManager重寫了DisplayObjectContainer的接口,它與Container一樣忽略輔助性的元素,通過SystemManager擷取的子級實際上不包含浮動視窗、工具提示和光标這樣的輔助層,也不包括内部的滑鼠捕捉層,隻包含預設的應用程式層和使用addChild()等方法添加進來的應用層,這也是SystemManager提供cursorChildren等這樣的集合通路而不是通過getChildAt()通路頂級顯示層的原因。通過cursorChildren這樣的集合也并不能完全暴露SystemManager的所有子級,要通路原始子級,可以使用rawChildren:IChildList屬性進行周遊,但不要通過此手段破壞SystemManager的結構。

載入Flex項目

SystemManager實作IFlexModuleFactory接口,但并不表示它可以作為一個Module載入,擴充IFlexModuleFactory是為了利用工廠模式分離preloader和Application的關聯。整個Flex項目确實可以載入到其它項目中的,但不是以Module方式載入而是通過普通方法加載,例如使用SWFLoader或Loader加載,SystemManager作為頂級容器加入到項目的顯示清單。

SystemManager的application:IUIComponent屬性引用載入Flex項目的application執行個體,getDefinitionByName(name:String):Object方法擷取載入swf中的定義,例如Object(SystemManager(mySwfLoader.content).application.testButton擷取載入項目中的testButton按鈕執行個體,SystemManager(mySwfLoader.content).getDefinitionByName("TestButton")擷取載入項目中的TestButtond定義。

将Flex項目載入到另一個Flex項目中後,會使用新項目的SystemManager管理頂級層,因為全局管理器隻能有一個,例如載入項目中有彈出視窗,這個彈出視窗的父級為新項目的SystemManager,原項目的SystemManager僅作為一個父級存在,它的功能隻限定于引用,原項目中可以使用topLevelSystemManager:ISystemManager屬性引用新項目的SystemManager。讓一個Flex項目載入另外一個Flex項目沒有什麼優勢,不能很好的展現項目和子產品的關系,代碼組織不明确且無法避免重定義,我們應該使用Module來分割應用程式。一個例外是你可以讓Flash項目載入Flex工程建構UI來代替Flash的v3元件架構,但你需要斟酌加載swf給Flash項目帶來的等待時間,Flex項目通常體積比較大。

Application

Application是應用層的頂級容器,Application的某些屬性關系到Flex如何編譯項目或生成的網頁,這些屬性不能用as設定,隻能通過mxml标簽設定,如下:

屬性 說明
frameRate:Number 項目幀數,預設為24幀
pageTitle:String 浏覽器标題欄中顯示的文本
usePreLoader:Boolean 是否顯示預加載器PreLoader
preloader:Object 預加載器類路徑
scriptRecursionLimit:int 最大堆棧
scriptTimeLimit:Number 最大失去響應時間

擷取swf位址和flashVars

Application的url:String可以擷取swf位址,但這個屬性依然不能擷取網頁傳遞的值對,因為Application是通過釋出swf的loaderInfo擷取位址,parameters:Object屬性映射了loadInfo的flashVars,通路flashVars參數比較友善。

初始化流程

Application和UIComponent的初始化過程涉及到很多方面,若揉雜在一起便會對維護和修改造成混亂的局面,于是Flex将初始化過程進行階段劃分并制定執行順序,每個階段完成都會觸發一個事件,這些事件不僅能夠反映初始化過程,還為我們提供了對初始化進行增補的手段。

UIComponent初始化流程

Flex元件和Flex容器都繼承UIComponent,它們的初始化流程都被定義在UIComponent中,這表示Flex元件和Flex容器的初始化流程是相同的,Flex元件雖然不能象容器那樣添加子級,但不代表它們沒有子級,如Button内部包含的UITextField,某些Flex元件和Flex容器一樣包括其它Flex元件,如Combox的子級包括List元件,這樣的元件稱為複合元件。Flex元件和Flex容器均采取遞歸的方式初始化,即先完成子級初始化,然後完成父級初始化,在初始化過程中伴随者事件,如圖:

Flex 頁面 初始化順序

在UIComponent的構造函數中不會建立元件的子級,構造函數中隻對元件的預設屬性、樣式進行設定,并且為元件添加偵聽器,子級是在initilize()方法中建立的,initilize()方法是UIcomponent初始化核心,它不由構造函數調用的,而是調用addChild()和addChildAt()方法時執行,好處是節省記憶體占用,初始化後的元件必然要占據大量的記憶體,動态添加的子級在加入容器之前保持其最小體積,直到加入容器時才具有正常的記憶體占用。在createChildren()方法中建立元件的子級,如果子級也是UIComponent,則會産生遞歸,preInitilize事件提供建立子級之前的準備工作,childrenCreated()和initilizationComplete()方法提供子級建立完畢之後的改造工作,差別是它們之間相隔一個initializeAccessibility()方法,initializeAccessibility()用于初始化輔助功能,當所有子級以及遞歸完成後,發送initilize事件,如果UIComponent是容器,則接着對元件進行布局,布局完成後發送creationComplete事件。了解initilize()方法工作原理對開發自定義元件非常重要,選擇繼承UIComponent時,應該把建立子級的代碼放入createchildren()方法中;選擇繼承内置元件時,可以在childrenCreated()或initilizationComplete()方法中對元件進行改造;如果隻需要對元件的屬性或者樣式進行設定,可以選擇preInitilize、initilize、事件在不同階段進行設定,要修改布局,可在creationComplete事件後進行。

Application初始化流程

Application的初始化過程不但包括内部子級的初始化,還通知SystemManager将其加入舞台的顯示清單,Application是Flex容器,它的初始化規則遵守普通元件的規則,這裡以事件為主線闡明Application在初始化過程中經曆的階段:

Flex 頁面 初始化順序

Application擁有普通容器沒有的ApplicationComplete事件,Application被SystemManager添加到顯示清單後觸發,完成度比createComplete更高,在這個事件中可以通路舞台。

初始化事件

初始化事件都是FlexEvent事件,對應類型如下表:

事件名稱 事件類型
preinitilize FlexEvent.PREINITIALIZE
initilize FlexEvent.INITIALIZE
creationComplete FlexEvent.CREATION_COMPLETE
applicationComplete FlexEvent.APPLICATION_COMPLETE
ui