Professional Documents
Culture Documents
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
2004 ԑ 5 Т
Copyright © 2004 Macromedia, Inc. ߳ܚԤ᠌ցȄ
ҏМӇϛ֤ܚϞၥଉфߒ Macromedia ҬࠉܻีРᄇܻܚଆ፣ϞដᚠݲࣼޟȄҥܻ Macromedia ҆ᄇᡐϽޟѿൟݷޑԤܚІᔖȂӰԪҏഋϷϚᔖೝ
၌ភ࣏ Macromedia ϞܛᒛȂи Macromedia ζฒ߳ݲᜌӵีРϞࡣܚю౪ޟӈդၥଉྥޟጂܒȄ
ҏҩҪਪ༉ټՃȄMACROMEDIA ϚᄇҏМӇϛϞӈդ݂ҰུܖҰϱৠඪ߳ټᜌȄ
Macromedia џᄇҏМϛܚϭಝϞᄇຫԤடցȃடցϞᔖҢȃ୦ȃհ᠌ڏܖтසኋ᠌Ȅଶߨ Macromedia оӈդਪ७௲᠌ӫघϞלԒ݂ጂඪ
юȂ֏ࠌҏМӇٮϚфߒ࣏ௌඪټٲடցȃ୦ȃհ᠌ڏܖтසኋ᠌Ϟ௲᠌Ȅ
Macromedia®ȃMacromedia ᇬȃMacromedia Dreamweaver®ȃMacromedia Flex® Ѕ Macromedia Flash® ࣏ Macromedia, Inc. ӵछЅ/ڏܖтড়
ޟ୦ܖຝы୦ȄҏМӇϛඪЅϞᄂሬϴѧᇄࠢӪᆎџ࣏ڏӨՌԤޱϞ୦Ȅ
Macromedia, Inc.
600 Townsend Street, Suite 500
San Francisco, CA 94103
415–252–2000
ii
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
Ҭᓃ
ஈᄢौ............................................................................................................................... 1
ғጂٺҢގ७ညȃቹڷϱ֤Ҭ ....................................................................................... 3
避免建立許多容器巢狀層次 ................................................................................................3
絕對定位與調整大小..........................................................................................................4
聰明地使用格線容器..........................................................................................................5
應避免的常見容器重複範例 ................................................................................................7
ٺҢ۽ᒶஈএᡝϽپਝ.............................................................................................. 9
導覽容器有內建延遲執行個體化 ..........................................................................................9
漸進式版面配置 ..............................................................................................................10
延遲動作........................................................................................................................16
౩σ໔ޟၥਟ ................................................................................................................ 16
ᄱӴኬܹፒӫ੫ਝ............................................................................................................. 16
ٺҢஈਢኺԒႀԙޟٹਝ.......................................................................................... 17
ഋဍᒵ............................................................................................................................ 27
Ґีپ… .......................................................................................................................... 31
ཎَᇄЛධ......................................................................................................................... 32
ᜰܻհޱ............................................................................................................................ 32
1
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
ஈᄢौ
Macromedia Flex 是功能強大的平台,提供建立 Rich Internet Application (RIAs)
的能力。不當使用會造成一些區域的效能變差。本文探討其中一些效能問題,並提供
如何運用下列兩個層級,來充份發揮 Flex 應用程式效能的提示:Flex 用戶端和 Flex
展示伺服器 (presentation server)。
Flex 與其他採用該特定編碼的程式設計模型一樣,可能會影響到應用程式在用戶端的
整體效能。本文說明某些會在用戶端影響應用程式效能的 MXML 編碼方式,並展示
加強 Flex 應用程式效能的簡單技術。
其中特別探討如何:
縮短啟動時間
運用延遲執行個體化來改善效能
順暢地播放複合特效
改善重複項物件的效能
處理大量的資料集
對 Flex 應用程式進行效能測試
對於伺服器,本文件的內容包括:
flexconfig.xml 檔與此檔案對效能的影響
Flex 快取模型
有效率地傳送資料至 Flex 用戶端
有效地運用 JSP 附加標籤庫
預先編譯 MXML 頁面
JVM 微調
Flex 部署選項
請注意,本文件中建議的提示並不適用於所有 Flex 應用程式。您必須先分析您應用
程式的結構,並依需求修改建議。若需持續的編碼與概念上的協助,您可使用 Flex
支援論壇
(www.macromedia.com/cfusion/webforums/forum/index.cfm?forumid=60) 和
Flex 開發人員中心 (www.macromedia.com/devnet/flex/)。
亦請注意,為充份運用本文件,您需要具備下列各項:
Macromedia Flex (www.macromedia.com/tw/software/flex/trial/)
Macromedia Flash Player 7
熟悉使用 Macromedia Flex 與 J2EE 應用程式伺服器(Jrun、IBM
Websphere、BEA Weblogic)
一些建立 Flex 應用程式的經驗。(理想狀態下,您應至少已建立過一個簡單的
Flex 應用程式。)
1
೩ॎюၼհيԁ ޟFlex ᔖҢแԒ࢜ᄺ
理想上,在開發程序的每個階段 - 從應用程式設計到實作乃至於部署 - 中,都應以
效能為主要考量。當建立 Flex 應用程式時,全盤思考您使用的各種容器和元件的選
擇,以確保程式碼是可以維護、組織清楚,而且運作良好。
您可在各種應用程式類型上,使用 Flex 導覽容器(navigator container)
(Accordion、TabNavigator 和 ViewStack)來組織內容。導覽容器組織內容的方
式可以:
將終端使用者的困擾降到最低
展現為以瀏覽器為主的應用程式所設計的良好使用者介面 (UI)
協助效能
尤其 Flex 導覽容器還可協助您輕鬆以不同的子系檢視,來組織內容,並使用延遲執
行個體化,來控制這些檢視的建立工作。在這些子系檢視中組織內容時,在建立每個
子系檢視時都需要一段時間,因為當使用者第一次要求特定子系檢視時,Flex 會建立
此子系檢視。本文稍後的「導覽容器有內建延遲執行個體化」一節說明為什麼 Flex
導覽容器與延遲執行個體化搭配使用時,就能提供較佳的效能,以及如何運用延遲執
行個體化,讓您的應用程式更加強穩。
而儀表板式的應用程式也帶來部署的成功。此種應用程式類型可將內容組織為模組化
的獨立檢視,為應用程式組織提供更具直覺式的方式。和導覽容器一樣,本方式也能
提供不錯的效能,因為當使用者向下切入時,它可使用 Flex 來組織複雜的檢視。
Flex 不需要在幕後調整大小、測量和繪製檢視,所以可以更迅速地建立選取的檢視。
2
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
ғጂٺҢގ७ညȃቹڷϱ֤Ҭ
影響 Flex 效能的最主要因素,是任意使用容器。因為使用過多的容器會大幅降低應
用程式的效能。這是 Flex 開發人員最常犯的效能錯誤 — 所幸可以完全避免這個錯
誤。之所以會發生效能降低的情況,是因為 Flex 版面配置管理員及其子系會依循調
整大小與測量演算法,來決定 x,y 位置、偏好大小及樣式。而這些計算需要大量資
源;因此這些計算加上運用 Flash Player 來繪製複雜物件的作業,會延緩 Flex 應用
程式在啟動時,或在導覽容器中執行個體化新檢視時的速度。要大幅提高應用程式啟
動速度與加快互動時間的原則就是:避免不必要的容器巢狀結構。
首先,您可能會覺得要找出多餘的容器巢狀結構並不容易。下列各節說明容器巢狀結
構的常見個案,並提供選擇與使用容器的有用秘訣。
ᗗջ࡚ҳ೨ӻৠᏢறޑቹԩ
最好的方法,就是不要建立超過三層的容器巢狀層次。下列為深層巢狀的範例:
<mx:VBox>
<mx:HBox>
<mx:Form>
<mx:FormItem>
...
...
</mx:FormItem>
</mx:Form>
</mx:HBox>
</mx:VBox>
以及
<mx:Grid>
<mx:GridRow>
<mx:GridItem>
<mx:VBox>
<mx:Button />
</mx:VBox>
</mx:GridItem>
</mx:GridRow>
</mx:Grid>
當您建立容器巢狀時,每個容器執行個體都會在其子系上執行測量與調整大小的演算
法(其中有些會在容器本身上執行,因此測量程序會遞迴執行)。在處理版面配置演
算法,並已計算相關的版面配置值時,Flash Player 就會繪製複雜的物件集合,以構
成整個檢視。藉由除去物件建立時的不必要工作,就可明顯大幅提高應用程式的效能。
通常,建立三層或三層以下的容器巢狀層次,建立時就可產生良好的效果。如果您發
現您建立超過三層的容器巢狀層次,請重新評估您的容器選擇。您也許可以使用不同
的版面配置容器與樣式屬性(例如水平和垂直對齊、邊界、隔板和間距),來產生相
同的版面配置。您可運用邊界和間距,來調整控制項四週,以及控制項邊緣與其父項
容器邊緣之間的空間。您可使用隔板物件來填滿不需要的空間,或在畫面上排列控制
項。您也可以在控制項的容器內,水平或垂直對齊控制項。例如,請參閱圖 1。您不
需使用「格線 (Grid)」容器就可產生此版面配置。
3
ყ 1Ȉ! 您不需使用「格線 (Grid)」容器就可產生此版面配置。
在編寫程式碼時,常會使用「格線 (Grid)」容器來產生此版面配置:
<mx:Grid>
<mx:GridRow>
<mx:GridItem>
<mx:Button label="Visa"/>
</mx:GridItem>
<mx:GridItem>
<mx:Button label="MasterCard"/>
</mx:GridItem>
<mx:GridItem>
<mx:Button label="Diner's Club"/>
</mx:GridItem>
<mx:GridItem>
<mx:Button label="AmEx"/>
</mx:GridItem>
</mx:GridRow>
</mx:Grid>
但是,這會使程式碼增加不必要的大小。事實上,您可輕鬆修改程式碼,讓它可看起
來完全像圖 1。下列程式片段只需較少的程式碼,而且還可以縮短建立時間,並產生
稍微小一點的 SWF 輸出。
<mx:HBox>
<mx:Button label="Visa"/>
<mx:Button label="MasterCard"/>
<mx:Button label="Diner's Club"/>
<mx:Button label="AmEx"/>
</mx:HBox>
๘ᄇۡ՝ᇄ፡ᐌσω
Flex 容器類別是相對的版面配置容器,可為您在畫面上安排內容。但是,解譯每個容
器及其子系的大小,以及放置它們的位置等計算作業,都需要大量的資源。以下提供
兩個秘訣,將有助於減少這類的計算:
4
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
ᖑ݂ӴٺҢਿጣৠᏢ
5
ყ 2Ȉ! 此 UI 最適合用於格線 (Grid) 容器。
6
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
ᔖᗗջޟலَৠᏢ१ፒጒٽ
以下列出應避免的常見容器重複範例:
7
您可使用此程式碼如下:
<mx:Panel title="Grocery List" width="150" height="150">
<mx:Label text="Fruits" />
<mx:Label text="Veggies" />
<mx:Label text="Cookies" />
<mx:Label text="Crackers" />
</mx:Panel>
兩者都可產生相同的版面配置。
VBox 內部的 <mx:Application> 標籤 - 應用程式物件本身就是 VBox 版面配
置。所以不需要使用 VBox 容器來包住應用程式。將此包裝函式移除,將可消除一
或多層容器巢狀結構。
例如,您不要編寫如下:
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml">
<mx:VBox horizontalAlign="center" backgroundColor="#EFEFEF">
<mx:Label label="Shopping Cart" />
.
.
.
</mx:VBox>
</mx:Application>
您可使用此程式碼如下:
<mx:Application xmlns:mx=http://www.macromedia.com/2003/mxml
horizontalAlign="center" backgroundColor="#EFEFEF">
<mx:Label label="Shopping Cart" />
.
.
.
</mx:Application>
8
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
ٺҢ۽ᒶஈএᡝϽپਝ
如果說,效能問題的頭號原因是多餘的容器巢狀產生的不必要測量和版面配置,那麼
第二個原因就是在尚未需要之前,就先建立物件。為避免這個問題,您可以使用延遲
執行個體化。Flex 使用延遲執行個體化來判斷在應用程式啟動時,要建立哪些元件。
在使用延遲執行個體化時,您可決定使用者在哪個階段進行元件建立。容器中包含一
個 creationPolicy 屬性,您可設定它來指定 Flex 何時建立容器(在啟動時、當使
用者導覽至該容器,或根據使用者的動作)。
Ᏺ។ৠᏢԤϱ࡚۽ᒶஈএᡝϽ
Flex 導覽容器(ViewStack、Accordin、TabNavigator)有內建的延遲執行個體
化。預設的延遲執行個體化操作是指 Flex 未在啟動時建立所有子系檢視,只有當使
用者導覽至該容器時才會觸發它。下列程式碼顯示兩個使用中的導覽容器
TabNavigator 和 ViewStack:
<mx:TabNavigator>
<mx:VBox id="tabNavView1">
<mx:LinkBar dataProvider="myViewStack" />
<mx:ViewStack id="myViewStack">
<mx:VBox id="view1" >
.
.
</mx:VBox>
<mx:VBox id="view2" >
.
.
</mx:VBox>
<mx:VBox id="view3" >
.
.
</mx:VBox>
</mx:ViewStack>
</mx:VBox>
<mx:VBox id="tabNavView2">
.
.
</mx:VBox>
</mx:TabNavigator>
9
TabNavigator 容器會建立 tabNavView1,因為它是當 Flex 執行個體化
TabNavigator 容器時,顯示的第一個檢視。執行個體化 tabNavView1 時,會對
LinkBar 和 ViewStack 的第一個檢視 (view1) 執行個體化。當使用者在 ViewStack
中與 LinkBar 互動,以選擇另一個檢視時,Flex 就會建立此檢視。Flex 會繼續以這
種方式,在呼叫導覽子代時才建立它們。
容器標籤上的 creationPolicy 屬性控制子系檢視的建立。下列清單說明在 Flex 導
覽容器中設定 creationPolicy 屬性時,其每個屬性的功能:
creationPolicy="auto" - 當 Flex 建立導覽容器時,並不會立即建立所有子
代,而僅會建立剛開始會出現的子代。延遲執行個體化的結果,會使具有導覽容
器的 MXML 應用程式載入的速度變快,不過當使用者從某一檢視第一次導覽至另
一檢視時,會出現短暫的停頓。可用性研究顯示,相較於讓使用者長時間等待應
用程式在啟動時建立導覽子系檢視,這種方式可提供較佳的使用者體驗。此外,
使用者也有可能永遠不會造訪其中某些子系檢視,因此在啟動時建立它們有可能
是多此一舉。
請注意,如果您在非導覽容器上設定 creationPolicy="auto",則必須加入額外
的程式碼,以指出何時要建立容器的子系。由於此額外程式碼已內建在導覽容器
中,所以您可直接在導覽容器上設定 creationPolicy="auto",而不需做額外的
工作。
creationPolicy="all" - 當 Flex 建立導覽容器時,會在所有子系檢視中建立所
有控制項。這項設定會延遲應用程式的啟動時間,但是可加速從某一檢視導覽至另
一個檢視時的回應時間。
creationPolicy="none" - Flex 會等到您明確呼叫執行個體化方法時,才會執
行個體化導覽容器中的元件或導覽容器的子系檢視。您可使用
createComponents() 方法明確執行個體化檢視。Flex 說明文件中提供有關設定
自訂元件建立計劃的詳細資訊。
運用 creationPolicy 屬性,您可手動建立子系檢視,並判斷要在應用程式架構的哪
個階段開始建立導覽容器子系檢視。可用性研究顯示,當使用 auto 設定時,可提供
較佳的使用者體驗。常見的錯誤,是在其中一個導覽容器上誤設了
creationPolicy="all",這會延遲應用程式的啟動時間。只有當您百分之百確定您
的元件建立計劃有效時,才能使用 creationPolicy="all"。
ᅚ໌Ԓގ७ည
您可以在微調效能的程序中,將應用程式的啟動時間儘可能縮到最短。但是,這不表
示您無法進一步提高效能;您可選擇使用漸進式版面配置。漸進式版面配置是一種 UI
概念,讓應用程式以逐一方式來配置元件版面,如此可縮短元件開始出現在螢幕上的
初始延遲時間。漸進式版面配置類似 HTML 應用程式連續將內容載入用戶端的方式。
漸進式版面配置雖無法量化降低應用程式的啟動時間,但卻可大幅改善使用者感受到
的啟動時間。
下列範例應用程式 ProgressiveLayoutExample.mxml 使用了漸進式版面配置。當
您執行應用程式時,您會看到應用程式以骨牌式檢視畫面,改善使用者感受到的啟動
時間。(您可從 Macromedia 網站下載此應用程式,網址為:
http://download.macromedia.com/pub/developer/solution_samples.zip。此應
用程式為範例檔案 (Sample Files) 下載檔的一部份下載。)
10
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
ProgressiveLayoutExample.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml"
creationComplete="createLater()">
<mx:Script>
<![CDATA[
function createNext(){
var nextObj = this[creationOrder[creationIndex++]];
nextObj.createComponents();
if(creationIndex < creationOrder.length){
nextObj.getChildAt(0).addEventListener("creationComplete",
mx.utils.Delegate.create(this, createLater));
}
}
function createLater(e:Object):Void{
doLater(this, "createNext");
}
]]>
</mx:Script>
<mx:HBox>
11
</mx:dataProvider>
</mx:List>
<mx:List width="190" height="95">
<mx:dataProvider>
<mx:Array>
<mx:String>red</mx:String>
<mx:String>green</mx:String>
<mx:String>yellow</mx:String>
<mx:String>blue</mx:String>
</mx:Array>
</mx:dataProvider>
</mx:List>
</mx:Panel>
<mx:Panel id="panel3" title="Panel 3" width="210" height="240"
horizontalAlign="center" verticalAlign="middle"
creationPolicy="none">
<mx:Tree width="190" height="95">
<mx:dataProvider>
<mx:XML>
<node label="File">
<node label="Open"/>
</node>
<node label="Close">
<node label="Help"/>
</node>
</mx:XML>
</mx:dataProvider>
</mx:Tree>
<mx:TextArea width="190" height="95">
<mx:text>The Macromedia Flex presentation server
offers a familiar, standards-based programming framework and
powerful set of components for creating a rich, responsive
presentation tier for enterprise Rich Internet Applications
(RIAs).</mx:text>
</mx:TextArea>
</mx:Panel>
</mx:HBox>
</mx:Application>
4 為 creationOrder 方法中指定的容器設定明確的寬度和高度值。如此,應用程式
就可判斷該容器的大小,而不需等容器填入子系時,再計算它的大小。如果您略過
此步驟,則會看到容器以預設的寬度和高度出現,然後當 Flex 建立子系時,再變
大以容納它們。這種重新調整大小的作業會耗用大量資源,而且不美觀。
您可先執行應用程式而不加入漸進式版面配置程式碼,以解譯容器的寬度和高度。
您可將容器的寬度和高度與兩個暫時標籤繫結。而繫結至標籤的寬度和高度為容器
的偏好大小,當您加入漸進式版面配置程式碼時,它們就是您設定的硬式編碼寬度
與高度值。下列程式碼片段說明如何解譯 HBox 容器的計算寬度和高度:
12
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
<mx:HBox id="firstBox">
..controls..
..controls..
</mx:HBox>
<mx:Label id="debug1" text="{firstBox.width}" />
<mx:Label id="debug2" text="{firstBox.height}" />
var creationOrder:Array;
function createNext(){
var nextObj = creationOrder.shift();
nextObj.createComponents();
if (creationOrder.length > 0) {
nextObj.getChildAt(0).addEventListener("creationComplete",
mx.utils.Delegate.create(this, createLater));
}
}
13
function createLater(e:Object):Void{
doLater(this, "createNext");
}
]]>
</mx:Script>
<mx:HTTPService id="serviceObject"
url="http://somesite.com/directory/myfile.xml" method="POST"
fault="alert(event.fault.faultstring);"
result="addToCreationOrderQueue(panel1,
serviceObject.companyDetailInfo);" resultFormat="object">
<mx:request>
<arg1>value1</arg1>
<arg2>value2</arg2>
</mx:request>
</mx:HTTPService>
14
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
</mx:HBox>
</mx:Application>
此範例應用程式使用漸進式版面配置,每個檢視都相依於資料服務傳入的資料。它會
使用來自不同資料服務傳回的資料填入子系,載入三個面板。您要確定只有當資料服
務已傳回其產生的資料時,才建立這三個面板。若要這麼做,您必須修改建立時機,
如此才能僅當對應的資料服務傳回結果時,才會使用物件填入 creationOrder 佇
列。您可使用資料服務的結果處理常式來進行這項工作,步驟如下:
1 在呼叫 addToCreationOrderQueue() 方法的資料服務標籤上,定義結果處理常
式。當對應資料傳回並可用來填入控制項時,此方法會將容器 id 加入
creationOrder 方法中。此方法的第二個參數 dataProvider 屬性,則為資料服
務傳回的資料。本步驟預設程式碼已在別處編寫好,以解析資料並準備將資料與
控制項繫結。
2 將 creationComplete="createLater()" 程式碼加入 <mx:Application> 標
籤。如此會觸發當該檢視的資料傳回時,建立第一個檢視。
3 複製程式碼至 <mx:Script> 區塊。此程式碼會處理將檢視加入 creationOrder
佇列的工作,並當其相依的資料傳回時,就開始建立檢視。
15
依這些步驟進行可保證只在檢視的資料可用時,才會建立該檢視。但是,上述程式碼
僅適用於 DataService_ProgressiveLayoutExample.mxml 專用的特定模組和檢
視。在加入漸進式展現(尤其當有相依資料時才建立檢視)時,通常需要視個別應用
程式來修改程式碼。
۽ᒶଢ଼հ
此方法會在目前呼叫的函數執行完成後,執行函數(第二個引數)。在本文稍早的
「漸進式佈局」一節所討論的漸進式版面配置範例應用程式
(ProgressiveLayoutExample.mxml) 中,您可看到使用 doLater() 方法的範例。
在該程式碼中,當剛建立的物件在繪製中時,creationComplete 事件就會執行。請
先等剛建立的物件繪製完成後,再開始建立下個物件。使用 doLater() 方法來完成
此延遲。簡單地說,creationComplete 事件處理常式會呼叫 doLater() 方法,而
不會馬上建立並繪製下個物件。
౩σ໔ޟၥਟ
有時您應用程式的速度會變慢,因為它正同時在管理大量的資料。Flex 團隊軟體工程
師 Matt Chotin 針對資料管理提出一些很好的建議,來處理這個問題他在他的 blog
中,討論如何整合分頁、排序及改善感受到的效能,網址為:
www.markme.com/mchotin/archives/cat_data_management.cfm。
ᄱӴኬܹፒӫ੫ਝ
您可能會注意到轉場特效有點不順暢,尤其當您將時間較短的特效套用在大型檢視上
時。不順暢的定義是什麼?例如,淡化 (Fade) 特效會明顯地以數個 alpha 階段分次
淡化,而不會流暢平順地淡化。或是縮效 (Zoom) 特效會明顯地以數個大小分次縮
放,而不會逐漸流暢地縮放。有幾個方式可調整個的轉場特效,使播放至順暢。請嘗
試下列建議組合,以找出最能改善您應用程式特效的方法。
使用時間長度屬性來提高特效的時間長度。如此可將明顯而不順暢的階段延伸為
較長的時間,讓肉眼填滿差異,或在觀看時感覺特效比較順暢。真的會產生不一
樣的效果。
在動畫中,Flash Player 越不需要重複繪製,特效在播放時就越順暢。如要這麼
做,讓目標檢視的一部份在特效開始時隱形,然後播放特效,等特效完成後,再顯
示那些部份。由於填入控制項的程序很快,所以肉眼不會察覺到任何延遲或控制項
突然出現。其編碼很簡單:進入 effectStart 和 effectEnd 事件,以控制在特效
前後要顯示的部份。這項技巧僅適用於當特效的時間長度較短時(500 微秒或更
短),且僅適用於 showEffect 或 hideEffect 事件。在其他情況下,隱藏物件
的部份看起來就不是那麼流暢了。
16
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
ٺҢஈਢኺԒႀԙޟٹਝ
執行時期階層式樣式的功能十分強大,但您應謹慎使用,並在適當的情況下使用。在
物件的執行個體上動態設定樣式意味著存取 UIObject 的 setStyle() 方法。在 Flex
應用程式模組架構中,呼叫 setStyle() 方法是最耗用資源的作業,因為此呼叫需要
通知所有剛建立樣式的物件的子系,去執行另一個樣式查閱作業。而必需通知的結果
子系樹狀結構可能會變得很大。
影響效能的常見錯誤,就是濫用或非必要地使用 setStyle() 方法通常,只有當您要
改變現有物件的樣式時,才需要用到 setStyle()。當您第一次設定物件樣式時,請
勿使用它。您可透過外部 CSS 樣式表或全域樣式,在 <mx:Style> 區塊中設定樣
式,做為 MXML 標籤上的明確樣式屬性。如果當程式執行(不論是您的應用程式、
導覽中的新檢視或動態建立的元件)時,您希望這些樣式不會改變,則必須使用正確
的樣式資訊來初始化物件(不論是您的應用程式、導覽中的新檢視或動態建立的元件)。
有些應用程式需要在應用程式或物件執行個體化時,呼叫 setStyle() 方法。此時,
則需要在執行個體化階段之前,先呼叫 setStyle() 方法,以避免非必要的查詢。在
執行個體化階段之前是指,在元件或應用程式的 initialize 事件(而不是在
creationComplete 或其他事件)中設定樣式。在初始時儘早設定樣式,您就可避免
非必要的樣式通知和查詢。
17
Repeater ސӇޟਝ
如有需要加速 Repeater 物件的效能,有幾個事項必須注意。首先,若將容器當作
Repeater 物件的子項使用,請確定容器沒有不必要的容器巢狀結構,而且愈簡潔愈
好。如果重複檢視的單一執行個體就要花上一段時間來產生,那麼重複的動作會更惡
化這種情形。如本文前面所述,多個 Grid 容器在 Repeater 物件中重複並不會獲得
良好的效能,原因是 Grid 容器本身就是需要耗費大量資源才能產生的容器。另一個
解決方法是使用 List 控制項加上自訂的儲存格轉換程式。
您也應將 recycleChildren 屬性設為 true 來改善 Repeater 物件的效能。
recycleChildren 屬性是一個布林 (Boolean) 值,當設為 true 時,會將新的資料項
目繫結到現有的 Repeater 子項,而有更多的資料項目時會逐漸建立新的子項,同時
摧毀不再需要的多餘子項。
當您將此屬性設為 false 時,如交換 dataProvider 屬性、執行排序等動作,
Repeater 物件就會重新建立所有重複的物件,因而造成效能延遲。以 FlexStore 為
例,存取網址為:
www.macromedia.com/flex/samples/flexstore/flexstore.mxml?versionCheck
ed=true,便使用了 recycleChildren。當您載入應用程式時,請注意產品縮圖檢視
下方的 Sort by(排序依據)選項。此選項可讓使用者依名稱或價格排序產品縮圖。
其實改變的並不是縮圖檢視,而是 Repeater object 物件的 dataProvider 屬性順
序。將 recycleChildren 屬性設為 true,Repeater 物件不會重新建立每個縮圖檢
視,而只是依據名稱或價格重新排列 dataProvider 屬性的順序。
recycleChildren 屬性的預設值是 false,這麼做可確保您不會將過期的狀態資訊
留在重複的執行個體中。舉例來說,假設您使用 Repeater 物件來顯示照片影像,而
每個 Image 控制項又有關聯的 NumericStepper 控制項來輸入訂購的份數。像是影
像等部份狀態資訊是來自 dataProvider 屬性,而其他狀態資訊,例如份數計算,則
是由使用者互動設定。如果您將 recycleChildren 屬性設為 true,然後遞增
Repeater 物件的 startingIndex 值來依頁排列照片,Image 控制項是會繫結到新
的影像,但 NumericStepper 控制項卻仍然還會是舊的資訊!只有在手動重設狀態資
訊太麻煩,或是確定修改 dataProvider 應不會觸發 Repeater 物件的子項重新建立
時,才應使用 recycleChildren="false"。
雖然這樣說有點多此一舉,但當 Repeater 物件第一次載入時,recycleChildren 屬
性對 Repeater 物件的速度並沒有影響。recycleChildren 屬性只會改善後續
Repeater 個體的效能。如果您確定 Repeater 物件只建立子項一次,就不需要使用
recycleChildren 屬性,也無須擔心過期的狀態資訊。
18
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
ᕣ၌ Flex Ұթ݈Ꮲϛڥפޟђ
Flex 使用記憶體內快取來處理 MXML 網頁的請求。當第一次叫用 MXML 網頁時,
編譯器會建立 SWF 檔案,並將檔案儲存在 Flex 快取中。Flex 也會建立並快取
HTML 封套 (Wrapper) 網頁,並從此快取處理後續的網頁請求。圖 5 顯示整個流程。
19
此程式碼片段會快取在 <mxml-size> 項目所定義的來源快取中。編譯來源所產生的
SWF 檔案及 HTML shell 將快取在 <content-size> 快取設定所定義的內容快取
中。若網頁中的來源片段有所變更,新的快取項目會加入來源快取中,而 Flex 會編
譯新的 SWF 檔案。
<mm:mxml>
<mx:Application>
<mx:Label text="Hello"/>
</mx:Application>
</mm:mxml>
ও flex-config.xml ಢᄘ೩ۡ
要改善實際執行環境的效能,最簡單的方法就是將 flex-config.xml 檔案中的
production-mode 屬性設為 true。這會在 Flex 中產生幾項效果。
20
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
Ԇ ڥFlex ၥਟ݈
您如何存取 Flex 應用程式中的資料,將對效能造成影響。由於應用程式在第一次要
求後會快取在瀏覽器上,因此資料存取會在應用程式執行時大幅影響效能。Flex 提供
幾種方法來將資料傳送到用戶端。它透過執行期服務來傳送資料,這些服務會叫用已
載入 Flex 類別路徑 (classpath) 的 Java 類別,或是將 proxy 要求傳送到網頁服務
或 HTTP 伺服器。圖 6 顯示可用的 Flex 資料服務。
21
</mx:RemoteObject>
<mx:RemoteObject id="ro" src="samples.StockBean" encoding="SOAP">
<mx:method name="getQuote">
</mx:method>
</mx:RemoteObject>
22
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
由於會不斷進行編譯,因此這並不是一個很好的方法。舉例來說,如果有 500 位個
別使用者同時存取此應用程式,session.username 的值就會有 500 個不同的值,
而導致另外 499 次的 MXML 編譯。這也會在快取中增加不少的項目。比較好的做法
是使用 Flex 標籤庫的 <param> 標籤,將變數傳遞到 Flex 應用程式。只要在 MXML
script 區塊中宣告變數,接著就可以使用該變數的值。下面的程式碼顯示了最佳的做
法,來解決前面程式碼所遇到的問題。如此一來,網頁只要編譯一次,而每次有個別
使用者存取應用程式時,應用程式便會透過 mm:param 值傳遞個別使用者名稱。
<% session.setAttribute("username", "brandon"); %>
<%@ taglib uri="FlexTagLib" prefix="mm" %>
<mm:mxml>
<mm:param name="userName" value="<%=
session.getAttribute("username") %>" />
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml"
width="200" height="200">
<mx:Script>
var userName:String;
</mx:Script>
<mx:Label id="uName" text="Hi {userName}"/>
</mx:Application>
</mm:mxml>
23
<param> 標籤可以用來傳遞簡單的值,但若要將 XML 樹狀結構或複雜物件傳到 Flex
應用程式時又該怎辦?下面範例顯示如何使用標籤庫,將 XML 傳遞到 MXML 文
件。做法有兩種,而哪種的效能較佳,要視 XML 為靜態或動態而定。若 XML 為靜
態,那麼將 JSP 程式碼嵌入 MXML 文件,會有較佳的效能,如下面範例所示:
<%@ taglib uri="FlexTagLib" prefix="mm" %>
<html>
<%
String tree="<node label='Option 1'><node label='Option
1.1'/><node label='Option 1.2'/></node><node label='Option
2'/>"; %>
<mm:mxml>
<mx:Application width="250" height="250"
xmlns:mx="http://www.macromedia.com/2003/mxml">
<mx:XML id="myTree">
<%= tree %>
</mx:XML>
<mx:Tree dataProvider="{myTree}"/>
</mx:Application>
</mm:mxml>
</html>
Ⴑӑጡឍ MXML ᆩॲ
前面有關快取的章節討論了為求最佳效能,您必須重新編譯 MXML 檔案,並在伺服
器重新啟動後將檔案載入到快取。另一個選擇是用遠端編譯器 mxmlc 預先編譯
MXML 網頁,然後建立自己的 HTML shell 來將 SWF 檔案載入瀏覽器。這可讓您
部署位元程式碼 (bytecode),但工作不僅僅只有讓 Flex 即時為您建立 HTML 封套。
由於像播放程式偵測及歷史管理等許多功能都不再自動產生,您必須將這些編碼到
HTML 封套中才能提供這些功能。
24
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
25
document.write(" <param name='flashVars'
value='historyUrl=%2Fflex%2Fflex%2Dinternal%2Fhistory%2Fhistor
y%2Ehtml&lconid=" + lc_id +"'>");
document.write(" <param name='src' value='TabNav.swf'>");
document.write(" <embed
pluginspage='http://www.macromedia.com/go/getflashplayer'
width='100%' height='100%'");
document.write("
flashVars='historyUrl=%2Fflex%2Fflex%2Dinternal%2Fhistory%2Fhi
story%2Ehtml&lconid=" + lc_id +"'");
document.write(" src='TabNav.swf'");
document.write(" />");
document.write("</object>");
</script>
<script language='javascript' charset='utf-8'>
document.write("<br><iframe src='/flex/flex-
internal/history/history.html' name='_history' frameborder='0'
scrolling='no' width='22' height='0'></iframe></br>");
</script>
26
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
ഋဍᒵ
您有兩種選擇可部署 Flex。您可以運用現有的硬體和應用程式伺服器,也可以將
Flex 部署在專屬的系統上。運用現有硬體是提高投資報酬的最佳方法。您可能擔心將
Flex 加入現有環境會使伺服器負載變重,造成現有基礎架構極大負擔。事實正好相
反。使用 Flex 反而可以減少伺服器負載。
將現有 JSP 或以 servlet 為基礎的應用程式改造成 Rich Internet Application
(RIA),可降低每個要求傳遞的資料量,進而減少伺服器負載。而且,HTML 應用程
式是以網頁為基礎,當有資訊提交到伺服器,或是用戶端從一網頁瀏覽到另一網頁
時,就需要重新整理整個網頁。每一次網頁載入都會佔用網路頻寬及伺服器資源。
RIA 運作起來就像桌面應用程式,而不是一系列的網頁。Flash Player 把用戶端介面
當作單一無中斷的流程,當用戶端從應用程式的一區段移到另一區段時,並不需要從
伺服器載入網頁。使用 RIA,瀏覽器只需載入 SWF 檔案一次,後續的所有要求都是
使用 XML 或 AMF 的較小資料導向要求。
另一種部署 Flex 但比較不建議的選擇是建立專屬 Flex 環境。在這種模型中,現有基
礎架構是透過網頁服務或 XML 餵送來提供資料連接功能。這種模型會大幅增加成本
及系統負荷,因為您必須在打算部署 Flex 的位置安裝並設定新硬體以及 J2EE 應用
程式伺服器。
JVM 及 J2EE 伺服器微調注意事項:Flex 支援各種 J2EE 應用程式伺服器,因此
很難列出針對伺服器效能微調的特定動作。最好是先到應用程式伺服器廠商網站尋找
有關微調的資源。Flex 中的編譯器及資料服務可能會在嚴重負載的情況下使用大量的
短期物件。由於需經常使用廢棄項目收集功能,有時候可能會導致延遲。如果您的
JVM 廠商與 J2EE 應用程式伺服器廠商不同,您可能需要瞭解如何微調 JVM 及廢
棄項目收集功能。
27
ٺҢ ActionScript ೩ۡᏢ
ॎᆗᔖҢแԒߑۖϽਢ
另一個更簡單的效能分析方法就是使用程式碼來估算啟動時間。下面這一段程式碼可
計算應用程式初始化時間(也就是 Application 物件建立、計算、排列及繪製所有子
物件所需的時間);這並不包括下載用戶端 SWF 或任何伺服器端處理(像是檢查
Flash Player 版本、檢查 SWF 快取等)所需的時間。下面的例子顯示範例 Flex 應
用程式在瀏覽器中被叫用時,會出現載有控制項的簡單表單,初始化所花的時間會輸
出在標籤中。
<?xml version="1.0" encoding="iso-8859-1"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml"
creationComplete="doLater(this,'doneNow')">
<mx:Script><![CDATA[
var dp = [{food:"apple", type:"fruit", color:"red"},
{food:"potato", type:"vegetable", color:"brown"}, {food:"pear",
type:"fruit", color:"green"},
{food:"orange", type:"fruit",
color:"orange"},{food:"spinach", type:"vegetable",
color:"green"},{food:"beet", type:"vegetable", color:"red"}];
function doneNow()
{
doLater(this, "reallyDoneNow");
}
function reallyDoneNow()
{
timerLabel.text += getTimer() + " ms"
}
]]></mx:Script>
<mx:Form>
<mx:FormHeading label="Sample Form" />
<mx:FormItem label="List Control">
<mx:List dataProvider="{dp}"
labelField="food"/>
</mx:FormItem>
<mx:FormItem label="DataGrid control">
<mx:DataGrid width="200"
dataProvider="{dp}"/>
</mx:FormItem>
<mx:FormItem label="Date controls">
<mx:DateChooser />
28
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
<mx:DateField />
</mx:FormItem>
<mx:FormItem label="Load Time">
<mx:Label id="timerLabel"
fontSize="12" fontWeight="bold" text="The application
initialized in "/>
</mx:FormItem>
</mx:Form>
</mx:Application>
首先是要取得應用程式啟動時間的基準讀數。請確定您已結束所有其他執行中的應用
程式、確認是否使用 Flash Player 的正式版,然後執行應用程式三次來取得三次初
始化時間。將這三次時間平均起來就是基準讀數。當您在進行效能微調時,應確定啟
動時間的確有比較快。
這段程式碼也可協助您找出應用程式執行最慢的部分,並確定是否能夠予以加速。若
要這麼做,請選擇性地將應用程式的部分移除,看看單一部分的啟動時間是否與整個
應用程式的啟動時間相當。此一反覆進行的程序可找出應用程式有問題的部分。比如
說,此一方法可能會顯示整個應用程式的啟動時間為 12 秒,而載入其中的「檢視
B」就需要 6 秒。「檢視 B」就是問題所在,您可加以探討並尋求提升效能的辦法。
這個方法比設定和使用 ActionScript 設定器來得簡單,不過所產生的資訊就沒那麼
詳細。
॒ၷกၐώڎ
29
表 1: 負載測試工具
免費工具 付費工具
॒ၷกၐጒٽ
案例 1
ਰ ٽ2
30
Flex Application ਝȈ
ҢИᆒᔖҢแԒᇄթ݈ᏢਝޟඪҰᇄ
ਰ ٽ3
Ґีپ…
目前推出的 Flex 是 1.0 版。在 Flex 以後的版本中,Macromedia 打算加強現有的
Flex 機制、加入更多編譯器最佳化功能、解決物件建立時間等較大的效能問題,並加
入可縮短啟動時間的新功能。Flex 未來將推出來大幅提高啟動效能的功能之一便是執
行期共用程式庫(Runtime Shared Library;RSL)。利用 RSL,您可將共用資產
轉成獨立檔案,以供個別下載和快取。這麼一來,當程式庫不常變動,便可提高效
能,而且也可支援用大量小型 MXML 應用程式來建立網站,而不會受限於只能用單
一 MXML 應用程式。此外,下一版 Flash Player 也以大幅加強效能為目標。隨著
Flex 及 Flash Player 不斷進步,物件建立時間、物件繪製時間以及 ActionScript
處理時間也將愈來愈短,將可建立更強大、回應速度更快的 Flex 應用程式。
31
ཎَᇄЛධ
我們已盡一切努力確保本文及所附程式碼的正確性。歡迎您針對本文提出意見以及有
關 Flex 效能的問題。若要傳送給我們意見,請使用 Macromedia 網站上的意見表。
意見表的網址為: www.macromedia.com/support/email/tutorial/main.cgi。
ᜰܻհޱ
Brandon Purcell 在四年前進入 Macromedia/Allaire 擔任 ColdFusion 及 JRun
產品支援工程師。他在專業服務事業群 (Professional Services Group) 負責協助客
戶進行架構規劃、程式碼檢查、自訂訓練、負載測試及效能微調等工作。他也負責一
些專案,包括 macromedia.com 新網站的叢集、負載測試及部署工作。他在
Macromedia 任職期間支援的產品包括 ColdFusion、JRun、Flash Remoting,
並針對 ColdFusion 及 JRun 使用叢集與高可用性撰寫了相關的白皮書及文章。他
目前在支援 Flex 的伺服器支援組織 (Server Support Organization) 擔任特殊問題
工程師 (escalation engineer)。歡迎造訪他的網站:www.bpurcell.org。
32