如果您要顯示大量 itemRenderer-無論在 DataGrid 還是在 AdvancedDataGrid 中-如果無法有效編寫這些 itemRenderer, 您的應用程序性能可能受到負面影響。以下是一些可能有所幫助的提示:
- 限制使用 itemRenderer 的列數。是否真的需要將每個列作爲自定 itemRenderer?有時需要這樣, 光芒太強是否會令用戶頭暈眼花?
- 嘗試不要過於頻繁地更改 itemRenderer 中元素的樣式。如果需要切換樣式 (例如, 綠色用於正值, 紅色用於負值) , 可考慮爲這些樣式創建兩個控制預設並使其中一個可見。更改樣式 Flex 中比較費時的任務之一。
- 不要將 Containers 用作 itemRenderer 的基礎。容器會佔用大量資源。少量使用它們, 效果還不錯; 但是根據 UIComponent 編寫 itemRenderer 效率更高。
切換樣式
以下 itemRenderer 根據數據字段的值切換組件。
Code:
- <mx:Canvas>
- <mx:Script><![CDATA private function lessThanZero() : Boolean {
- return data.price < 0; }
- ]]></mx:Script>
- <mx:Label text="{data.price}" color="#FF0000" visible="{lessThanZero()}" />
- <mx:Label text="{data.price}" color="#00FF00" visible="{!lessThanZero()}" />
- </mx:Canvas>
這比設置樣式要快。要注意的其他事項包括:
- 避免數據綁定到樣式。更改樣式不僅比大多數操作要慢, 而且在它上面添加數據綁定代碼只會使它更糟。
- 使用 Canvas 或擴展 ListItemRenderer 或作爲 itemRenderer 的根。這允許您將控制放在各自上方。
擴展 UIComponent
目前編寫 itemRenderer 最有效的方式是使用 ActionScript 類擴展 UIComponent。您可以全面控制代碼, 並且渲染器也可以儘可能高效。
從上例切換樣式開始, 編寫一個擴展 UIComponent 的簡單 itemRenderer。
Code:
- package renderers
- {
- import mx.controls.listClasses.IListItemRenderer;
- import mx.core.UIComponent;
- public class PriceItemRenderer extends UIComponent implements IListItemRenderer
- {
- public function PriceItemRenderer()
- {
- super();
- }
- }
- }
您會發現我不僅編寫這個類來擴展 UIComponent, 還由它實施 IListItemRenderer 接口。這樣做是有必要的, 因爲 List 控制將需要任何渲染器實施該接口, 否則您會收到運行時錯誤, 因爲列表嘗試將渲染器轉換爲該接口。
如果閱讀 IListItemRenderer 的相關文檔, 您會發現這是一個許多其他接口的集合, UIComponent 會爲您實施其中的大多數。但有一個 IListItemRenderer 擴展的接口是 UIComponent 不實施的:IDataRenderer。這需要您添加代碼, 爲 itemRenderer 類提供您一直使用的 data 屬性。
如果您嘗試不實施 IDataRenderer 就使用這個類, 則編譯代碼時會收到以下錯誤:
- 1044:類 renderers:PriceItemRenderer 未實施名稱空間 mx.core:IDataRenderer 中的接口方法 get data。
編輯這個類並將它更改爲以下內容:
Code:
- package renderers
- {
- import mx.controls.listClasses.IListItemRenderer;
- import mx.core.UIComponent;
- import mx.events.FlexEvent;
- public class PriceItemRenderer extends UIComponent implements IListItemRenderer
- {
- public function PriceItemRenderer()
- {
- super();
- }
- // Internal variable for the property value.
- private var _data:Object;
- // Make the data property bindable.
- [Bindable("dataChange")]
- // Define the getter method.
- public function get data():Object {
- return _data;
- }
- // Define the setter method, and dispatch an event when the property
- // changes to support data binding.
- public function set data(value:Object):void {
- _data = value;
- dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
- }
- }
- }
我直接使用 IDataRenderer 的 Flex 文檔中的代碼, 這樣您都不用自己鍵入它。
1.移除它後, 您可以加入兩個標籤。添加變量用於存放這兩個標籤。
private var posLabel:Label; private var negLabel:Label;
2..將 set data 函數修改爲調用 invalidateProperties()。這很重要, 因爲更改數據必須更改標籤中的文本以及它們的可視性。
Code:
- public function set data(value:Object):void {
- _data = value;
- invalidateProperties();
- dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
- }
調用 invalidateProperties() 會告知 Flex 框架在適當的時間調用 commitProperties() 函數。
3.覆蓋 createChildren() 並創建標籤, 添加它們以顯示組件列表。注意, 除了創建標籤外, 還會設置它們的樣式和 visible 屬性。
Code:
- override protected function createChildren() : void
- {
- super.createChildren();
- posLabel = new Label();
- posLabel.visible = false;
- posLabel.setStyle("color", 0×00FF00);
- addChild(posLabel);
- negLabel = new Label();
- negLabel.visible = false;
- negLabel.setStyle("color", 0xFF0000);
- addChild(negLabel);
- }
4.覆蓋 commitProperties()
以設置標籤的文本和可視性。過去, 您一直通過覆蓋 set data
進行這類更改, 如果您喜歡, 也可以在這個類中那樣做。
Code:
- override protected
- function commitProperties():void
- {
- super.commitProperties();
- posLabel.text = data.price;
- negLabel.text = data.price;
- posLabel.visible = Number(data.price) > 0;
- negLabel.visible = Number(data.price) < 0;
- }
5.覆蓋 updateDisplayList()
以設置標籤大小並進行定位。您必須設置標籤大小, 因爲它們的默認大小爲 0×0。這是 Container 類將爲您做的另一件事。由於這個 itemRenderer 十分簡單, 您只需將標籤大小設置爲與 itemRenderer 大小匹配即可。
Code:
- override protected function updateDisplayList(
- unscaledWidth:Number, unscaledHeight:Number ) : void
- {
- super.updateDisplayList(unscaledWidth, unscaledHeight);
- posLabel.move(0,0);
- posLabel.setActualSize(unscaledWidth,unscaledHeight);
- negLabel.move(0,0);
- negLabel.setActualSize(unscaledWidth, unscaledHeight);
- }
所有這些只能做到這點似乎有點複雜, 但是請記住一點, 使用容器增加的代碼要比這多得多。
UIComponent 附註
UIComponent 類是所有可視 Flex 組件 (控制和容器) 的基礎。以下是將 UIComponent 用作 itemRenderer 的一些相關提示。
- UIComponent 對其子代 (如 Container) 沒有版面限制。您必須自己進行子代定位並調整大小。
- 還可以超出 updateDisplayList() 中指定的大小繪製圖形和位置子代。
- 如果準備在列表中使用 variableRowHeight, 您還應覆蓋 measure() 函數, 告知列表 itemRenderer 有多大。
- 要將 UIComponent 用作 itemRenderer, 您必須實施 IDataRenderer。
- 要使用 listData 屬性, 您必須實施 IDropInListItemRenderer; 本系列之前的文章中討論過這個操作。
後續工作
有關 Flex itemRenderer 的系列到此結束。希望您通過這些文章瞭解到使用 itemRenderer 可以在 Flex 應用程序中做些什麼以及如何處理它們的數據、外觀和行爲的最佳做法。您可以在 Adobe Flex 3 文檔*中找到 Flex itemRenderer 的更多相關信息。