理解 Flex itemRenderer - 第 5 部分: 效率

如果您要顯示大量 itemRenderer-無論在 DataGrid 還是在 AdvancedDataGrid 中-如果無法有效編寫這些 itemRenderer, 您的應用程序性能可能受到負面影響。以下是一些可能有所幫助的提示:

  • 限制使用 itemRenderer 的列數。是否真的需要將每個列作爲自定 itemRenderer?有時需要這樣, 光芒太強是否會令用戶頭暈眼花?
  • 嘗試不要過於頻繁地更改 itemRenderer 中元素的樣式。如果需要切換樣式 (例如, 綠色用於正值, 紅色用於負值) , 可考慮爲這些樣式創建兩個控制預設並使其中一個可見。更改樣式 Flex 中比較費時的任務之一。
  • 不要將 Containers 用作 itemRenderer 的基礎。容器會佔用大量資源。少量使用它們, 效果還不錯; 但是根據 UIComponent 編寫 itemRenderer 效率更高。

切換樣式

以下 itemRenderer 根據數據字段的值切換組件。

Code:

  1. <mx:Canvas>
  2. <mx:Script><![CDATA private function lessThanZero() : Boolean {  
  3.            return data.price < 0; }  
  4.     ]]></mx:Script>
  5. <mx:Label text="{data.price}" color="#FF0000" visible="{lessThanZero()}" />
  6. <mx:Label text="{data.price}" color="#00FF00" visible="{!lessThanZero()}" />
  7. </mx:Canvas>

這比設置樣式要快。要注意的其他事項包括:

  • 避免數據綁定到樣式。更改樣式不僅比大多數操作要慢, 而且在它上面添加數據綁定代碼只會使它更糟。
  • 使用 Canvas 或擴展 ListItemRenderer 或作爲 itemRenderer 的根。這允許您將控制放在各自上方。

擴展 UIComponent

目前編寫 itemRenderer 最有效的方式是使用 ActionScript 類擴展 UIComponent。您可以全面控制代碼, 並且渲染器也可以儘可能高效。

從上例切換樣式開始, 編寫一個擴展 UIComponent 的簡單 itemRenderer。

Code:

  1. package renderers  
  2. {  
  3.       import mx.controls.listClasses.IListItemRenderer;  
  4.       import mx.core.UIComponent;  
  5.       public class PriceItemRenderer extends UIComponent implements IListItemRenderer  
  6.       {  
  7.            public function PriceItemRenderer()  
  8.            {  
  9.                  super();  
  10.            }  
  11.       }  

您會發現我不僅編寫這個類來擴展 UIComponent, 還由它實施 IListItemRenderer 接口。這樣做是有必要的, 因爲 List 控制將需要任何渲染器實施該接口, 否則您會收到運行時錯誤, 因爲列表嘗試將渲染器轉換爲該接口。

如果閱讀 IListItemRenderer 的相關文檔, 您會發現這是一個許多其他接口的集合, UIComponent 會爲您實施其中的大多數。但有一個 IListItemRenderer 擴展的接口是 UIComponent 不實施的:IDataRenderer。這需要您添加代碼, 爲 itemRenderer 類提供您一直使用的 data 屬性。

如果您嘗試不實施 IDataRenderer 就使用這個類, 則編譯代碼時會收到以下錯誤:

  • 1044:類 renderers:PriceItemRenderer 未實施名稱空間 mx.core:IDataRenderer 中的接口方法 get data。

編輯這個類並將它更改爲以下內容:

Code:

  1. package renderers  
  2. {  
  3.       import mx.controls.listClasses.IListItemRenderer;  
  4.       import mx.core.UIComponent;  
  5.       import mx.events.FlexEvent;  
  6.       public class PriceItemRenderer extends UIComponent implements IListItemRenderer  
  7.       {  
  8.            public function PriceItemRenderer()  
  9.            {  
  10.                  super();  
  11.            }  
  12.     // Internal variable for the property value.  
  13.     private var _data:Object;  
  14.     // Make the data property bindable.  
  15.     [Bindable("dataChange")]  
  16.     // Define the getter method.  
  17.     public function get data():Object {  
  18.         return _data;  
  19.     }  
  20.     // Define the setter method, and dispatch an event when the property  
  21.     // changes to support data binding.  
  22.     public function set data(value:Object):void {  
  23. _data = value;  
  24.         dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));  
  25.     }  
  26.    }  

我直接使用 IDataRenderer 的 Flex 文檔中的代碼, 這樣您都不用自己鍵入它。

1.移除它後, 您可以加入兩個標籤。添加變量用於存放這兩個標籤。
private var posLabel:Label; private var negLabel:Label;
2..將 set data 函數修改爲調用 invalidateProperties()。這很重要, 因爲更改數據必須更改標籤中的文本以及它們的可視性。

Code:

  1. public function set data(value:Object):void {  
  2. _data = value;  
  3.     invalidateProperties();  
  4.     dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));  

調用 invalidateProperties() 會告知 Flex 框架在適當的時間調用 commitProperties() 函數。
3.覆蓋 createChildren() 並創建標籤, 添加它們以顯示組件列表。注意, 除了創建標籤外, 還會設置它們的樣式和 visible 屬性。

Code:

  1. override protected function createChildren() : void          
  2. {                  
  3.      super.createChildren();  
  4. posLabel = new Label();             
  5. posLabel.visible = false;        
  6.      posLabel.setStyle("color", 0×00FF00);         
  7.      addChild(posLabel);                 
  8. negLabel = new Label();             
  9. negLabel.visible = false;               
  10.      negLabel.setStyle("color", 0xFF0000);             
  11.      addChild(negLabel);         

4.覆蓋 commitProperties() 以設置標籤的文本和可視性。過去, 您一直通過覆蓋 set data 進行這類更改, 如果您喜歡, 也可以在這個類中那樣做。

Code:

  1. override protected  
  2. function commitProperties():void             
  3. {                  
  4.      super.commitProperties();  
  5. posLabel.text = data.price;  
  6. negLabel.text = data.price;      
  7. posLabel.visible = Number(data.price) > 0;       
  8. negLabel.visible = Number(data.price) < 0;             

5.覆蓋 updateDisplayList() 以設置標籤大小並進行定位。您必須設置標籤大小, 因爲它們的默認大小爲 0×0。這是 Container 類將爲您做的另一件事。由於這個 itemRenderer 十分簡單, 您只需將標籤大小設置爲與 itemRenderer 大小匹配即可。

Code:

  1. override protected function updateDisplayList(  
  2. unscaledWidth:Number, unscaledHeight:Number ) : void  
  3. {          
  4.      super.updateDisplayList(unscaledWidth, unscaledHeight);           
  5.      posLabel.move(0,0);     
  6.      posLabel.setActualSize(unscaledWidth,unscaledHeight);       
  7.      negLabel.move(0,0);         
  8.      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 的更多相關信息。

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