Adobe Flex UIComponent LifeCycle

Adobe Flex UIComponent LifeCycle
(圖片來源於jexchan)

重寫Flex組件AS方式和MXML方式的採用推薦規則

  • MXML文件和AS文件最後都會被編譯成AS類,只不過MXML編譯速度稍慢一些
  • 如果MXML和AS都能完成的一個簡單Flex組件,MXML更容易被創建和控制佈局
  • 當要覆蓋Flex組件的某些方法時只能用AS方式
  • 創建非可視化Flex組件比如Formatter、validator、Effect……時,只能用AS
  • 要爲Flex組件添加日誌功能時,只能用AS.

參考代碼推薦:mx.controls.Button,在SDK裏面,現在都是openSouce的,所以可以參考Adobe是怎麼寫的。

createChildren()
可在自身內部創建其它組件或對象的組件。
無需直接調用此方法,addChild() 方法時,Flex 將調用 createChildren () 方法。也這是因爲這種特性,如果UIComponent沒有被加載到舞臺上,它裏面的children是不會被實例化的,也正是新手常常碰到錯誤的情況之一。

commitProperties()
提交Flex組件所有的屬性變化,設置measure()方法可能使用的屬性值。絕大多數情況下,都是對影響Flex組件如何在屏幕上顯示的屬性使用這個方法。
無需直接調用此方法,addChild() 或 invalidateProperties () 方法時,Flex 將調用 commitProperties () 方法。
應在調用 measure() 方法之前調用 commitProperties() 方法。這允許您設置 measure() 方法可能會用到的屬性值。

measure()
計算組件的默認大小和(可選)默認最小大小。
measuredWidth measuredHeight measuredMinWidth measuredMinHeight
無需直接調用此方法,addChild() 或 invalidateSize() 方法時,Flex 將調用 measure() 方法。

Container. layoutChrome()
layoutChrome是Container特有的生命週期,主要是跟容器邊框有關係。
通過設置此容器邊框的位置和大小響應大小更改。用於定義容器的邊框區域和確定邊框區域的位置,以及確定要在邊框區域中顯示的附加元素。
通常,使用RectangularBorder類來定義容器區域的邊框,而不是用圖片資源去包圍Flex組件。比如創建一個RectangularBorder對象,然後在重載的createChildren()方法中,將其作爲一個內容子控件添加到Flex組件中,再用updateDisplayList()方法來確定其位置。
將容器的內容區域和容器邊框區域分開處理的主要原因是爲了應對Container.autoLayout屬性被設置爲false的這種情況。當autoLayout(自動佈局)屬性使用默認值true時,只要容器子控件的大小和位置發生變化,容器及子控件就會進行度量和佈局。而當其爲false時,度量和佈局只在子控件被添加或移出容器時才執行。分開處理讓Flex在這兩種情況下都執行layoutChrome(),從而在autoLayout屬性爲false的情況下,容器仍能夠更新它的邊框區域。

updateDisplayList()
繪製對象和/或設置其子項的大小和位置。
無需直接調用此方法,addChild() 或 invalidateDisplayList () 方法時,Flex 將調用 updateDisplayList () 方法。
根據以前所設置的屬性和樣式來確定Flex組件的子Flex組件在屏幕上的大小(size)及位置(position),並且畫出Flex組件所使用的所有皮膚(skins)及圖形化元素。Flex組件的父容器負責確定Flex組件本身大小(size)。
要在updateDisplayList()方法中確定一個Flex組件的大小,當子Flex組件是UICOMPONENT時使用setActualSize()方法,而不是UICOMPONENT則使用與Flex組件大小相關的屬性width和height。要確定Flex組件的位置,當子Flex組件是UICOMPONENT時使用move() 方法,而不是UICOMPONENT則使用x和y屬性。一個區別就是move() 方法不僅改變了Flex組件位置,而且在調用這個方法之後立即分發了一個move事件,設置x和y屬性也更改Flex組件的位置,但卻在下一個屏幕更新事件中才會分發move事件。

在上述任一操作中,您都應使用組件的 unscaledWidth 和 unscaledHeight 作爲其邊界,而不是 width 和 height 屬性,這很重要。
以像素爲單位的Flex組件座標系中,unscaledWidth和unscaledHeight是由父容器確定的Flex組件大小,而不管Flex組件的scaleX,scaleY是多少。縮放發生在FlashPlayer或者AIR中,發生時機是在updateDisplayList()執行之後。比如一個Flex組件的unscaledHeight屬性是100,而其scaleY屬性是2.0,那麼它在FlashPlayer或AIR中出現的高度爲200像素。

深入Flex生命週期

  1. 調用Flex組件構造函數。構造函數沒有返回類型,沒有參數,使用super()調用父類的構造器。
  2. 使用set,get設置Flex組件屬性,常在set方法內監控一個布爾變量來實現失效機制。
  3. 調用addChild()方法將Flex組件添加到父Flex組件顯示列表中,Flex將自動調用createChildren(),invalidateProperties(),invalidateSize(),invalidateDisplayList()。只有將Flex組件添加到父容器中,Flex才能確定它的大小(size),設置它所繼承樣式(style)屬性,或者在屏幕上畫出它。
  4. Flex組件的parent屬性設置爲對父容器的引用。
  5. 樣式(style)設置。
  6. Flex組件分發preinitialize事件。
  7. 調用Flex組件createChildren()方法。
  8. 調用invalidateProperties(),invalidateSize(),invalidateDisplayList()失效方法,Flex將在下一個“渲染事件”(renderevent)期間對相應的commitProperties(),measure(),updateDisplayList()方法進行調用。
    這個規則唯一例外就是當用戶設置Flex組件的height和width屬性時,Flex不會調用measure()方法。也就是說,只有當Flex組件的explicitWidth和explicitHeight屬性是NaN時Flex纔會調用measure()方法。
  9. Flex組件分發initialize事件。此時Flex組件所有的子Flex組件初始化完成,但Flex組件尚未更改size和佈局,可以利用這個事件在Flex組件佈局之前執行一些附加的處理。
  10. 在父容器上分發childAdd事件。
  11. 在父容器上分發initialize事件。
  12. 在下一個“渲染事件”(renderevent)中,Flex執行以下動作:
    調用Flex組件的commitProperties()方法
    調用Flex組件的measure()方法
    調用Flex組件的layoutChrome()方法
    調用Flex組件的updateDisplayList()方法
    在Flex組件上分發updateComplete事件
  13. 如果commitProperties(),measure(),updateDisplayList()方法調用了invalidateProperties(),invalidateSize(),invalidateDisplayList()方法,則Flex會分發另外一個render事件
  14. 在最後的render事件發生後,Flex執行以下動作:
    設置Flex組件visible屬性使其可視
    Flex組件分發creationComplete事件,Flex組件的大小(size)和佈局被確定,這個事件只在Flex組件創建時分發一次
    Flex組件分發updateComplete事件。無論什麼時候,只要Flex組件的佈局(layout),位置,大小或其它可視的屬性發生變化就會分發這事件,然後更新Flex組件來正確地顯示。

失效機制(invalidation mechanism)
原理請看Essential.ActionScript.3.0(ActionScript.3.0 編程精髓)第二十三章的Event.RENDER部分。
一種情況是,當設置了Flex組件的多個屬性後,
比如
Button控件的label和icon屬性,我們需要所有屬性被設置後一次性執行commitProperties(),measure(),updateDisplayList()方法,而不是設置過label屬性後執行一遍這些方法,然後在設置icon屬性後又執行一次這些方法。
另一種情況是幾個Flex組件同時更改了它們的字體大小。程序更改字體大小的執行速度大大快於Flex更新應用的速度,因此要在確定最終更改字體之後纔開始更新佈局。
另外,Flex需要協調佈局操作以消除任何冗餘過程,而不是在每個Flex組件更新它的字體大小之後都執行一次佈局操作。
Flex使用“失效機制(invalidation mechanism)”來同步Flex組件的更改。Flex用一系列方法的調用,比如在setter方法內監控一個變更變量來標記Flex組件的某些東西已經發生變化,然後在下一個“渲染事件(renderevent)”中觸發Flex組件的commitProperties(),measure(),layoutChrome(),updateDisplayList()檢查這些布爾變量來完成最終的變更邏輯。這樣做的額外好處就是setter方法可以更迅速地返回,把對新屬性值的處理留給了commitProperties()方法。

失效方法及其對應的觸發函數如下:
invalidateProperties()通知Flex組件,以使下次屏幕更新時,它的commitProperties()方法被調用。
invalidateSize()通知Flex組件,以使下次屏幕更新時,它的measure()方法被調用。
invalidateDisplayList()通知Flex組件,以使下次屏幕更新時它的layoutChrome()方法和updateDisplayList()方法能被調用。
當Flex組件調用一個“失效”方法時,它就通知Flex該Flex組件已經被更新。當多個Flex組件調用失效方法,Flex會在schedules中協調這些更新,以使這些更新操作在下一次屏幕更新時一起執行。注意,createChildren()沒有對應的失效方法,它會在調用後被立即執行。

*名詞解釋
width : Number
指定組件在父座標中的寬度的數字(以像素爲單位)。
height : Number
指定組件在父座標中的高度的數字(以像素爲單位)。

explicitWidth : Number
指定該組件在組件座標中顯式寬度(以像素爲單位)的數字。
explicitHeight : Number
指定該組件在組件座標中顯式高度(以像素爲單位)的數字。

measuredWidth : Number
組件的默認寬度(以像素爲單位)。
measuredHeight : Number
組件的默認高度(以像素爲單位)。

percentWidth : Number
以組件父項大小百分比形式指定其寬度的數字。
percentHeight : Number
以組件父項大小百分比的方式指定組件高度的數字。

上述就是整個Adobe Flex UIComponent LifeCycle的內容整理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章