天天看點

Flex元件生命周期

Flex元件生命周期

(圖檔來源于jexchan)

Flex的根對象就是SystemManager,而不是我們平常看到的Application。

SystemManager是第一個在Flex應用中被建立的Display Class,繼承自flash.dispaly.MovieClip,是以才能實作Preloader和Application的2個frame。

SystemManager有一個topLevelSystemManager對象,指向一個SystemManager執行個體,是所有目前在flash player運作的任何東西的根(root),如果flex被作為主應用加載到flash player則上述屬性将指向其本身(self-refrencing),但當flex應用是被另一flex應用載入的,其自身的SystmenManager的topLevelSystemManager屬性則不是自引用了,而是指向其父應用的SystemManager執行個體。所有UIComponent的子類都有一個systemManager屬性指向應用的SystemManager執行個體,在被SystemManger執行個體監聽的component的事件發生冒泡時,其将擁有事件處理鍊上最後的處理權。

Preloader

Preloader是一個輕量級的類,在systemManager的第一幀被執行個體化,preloader會dispatch出一系列的事件,由progress bar監聽實作loading界面,一旦應用進入第二幀待application初始化後會借由system manager通知preloader初始化進度,preloader通知system manager其準備待删除,主要是一些初始化設定和下載下傳runtime share library。

Preloader的事件: 

progress

Indicates download progress

complete

Indicates that the download is complete

rslError

Indicates that a runtime shared library could not load

rslProgress

Indicates the download progress for a runtime shared library

rslComplete

Indicates that the download is complete for runtime shared libraries

initProgress

Indicates that the application is initializing

initComplete

Indicates that the application has initialized

在了解Preloader的同時也要反方向思考純AS工程中如何做Preloader,以前就寫過AS3工程 Custom Preloader 動態加載 Application可以進行思考。

Application

Application是我們平日用到的最多的類,在systemManager的第二幀被執行個體化,它是一個單例化的類,是以無論你new多少個Class它都會指向同一個instance實體,根據建立時間的進度,它同樣會dispatch出一系列的事件。

Application的事件:

preinitialize

application已經執行個體化但尚未建立任何child component

initialize

已經建立child component但未對其進行布局(lay out)

creationComplete

application已經完成執行個體化并完成所有child component的布局

applictionComplete

已經準備完成Flex SWF必要的初始化

上述就是整個Adobe Flex Application LifeCycle的内容整理。

Flex元件生命周期

(圖檔來源于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生命周期

調用Flex元件構造函數。構造函數沒有傳回類型,沒有參數,使用super()調用父類的構造器。 使用set,get設定Flex元件屬性,常在set方法内監控一個布爾變量來實作失效機制。 調用addChild()方法将Flex元件添加到父Flex元件顯示清單中,Flex将自動調用createChildren(),invalidateProperties(),invalidateSize(),invalidateDisplayList()。隻有将Flex元件添加到父容器中,Flex才能确定它的大小(size),設定它所繼承樣式(style)屬性,或者在螢幕上畫出它。 Flex元件的parent屬性設定為對父容器的引用。 樣式(style)設定。 Flex元件分發preinitialize事件。 調用Flex元件createChildren()方法。 調用invalidateProperties(),invalidateSize(),invalidateDisplayList()失效方法,Flex将在下一個“渲染事件”(renderevent)期間對相應的commitProperties(),measure(),updateDisplayList()方法進行調用。

這個規則唯一例外就是當使用者設定Flex元件的height和width屬性時,Flex不會調用measure()方法。也就是說,隻有當Flex元件的explicitWidth和explicitHeight屬性是NaN時Flex才會調用measure()方法。 Flex元件分發initialize事件。此時Flex元件所有的子Flex元件初始化完成,但Flex元件尚未更改size和布局,可以利用這個事件在Flex元件布局之前執行一些附加的處理。 在父容器上分發childAdd事件。 在父容器上分發initialize事件。 在下一個“渲染事件”(renderevent)中,Flex執行以下動作:

調用Flex元件的commitProperties()方法

調用Flex元件的measure()方法

調用Flex元件的layoutChrome()方法

調用Flex元件的updateDisplayList()方法

在Flex元件上分發updateComplete事件 如果commitProperties(),measure(),updateDisplayList()方法調用了invalidateProperties(),invalidateSize(),invalidateDisplayList()方法,則Flex會分發另外一個render事件 在最後的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的内容整理。

繼續閱讀