加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

提高flex性能之itemRenderer篇

发布时间:2020-12-15 01:12:23 所属栏目:百科 来源:网络整理
导读:之前我有总结过 如何提高 flex 性能 的文章,最近又碰到一个问题,就是对大批量数据的时候 DataGrid 中采用很多 itemRenderer ,性能将是一个大问题。于是寻找有关权威文章,期望能有所收获。在 Peter Ent 的 blog 上还是得到了不少帮助,原文是英文,也有人

之前我有总结过如何提高flex性能的文章,最近又碰到一个问题,就是对大批量数据的时候DataGrid中采用很多itemRenderer,性能将是一个大问题。于是寻找有关权威文章,期望能有所收获。在Peter Entblog上还是得到了不少帮助,原文是英文,也有人做过翻译,我这里就简单提取一部分仅供参考。需要详细,建议查看原文。

当我们在用itemRenderer显示大量数据的时候,无论是在DataGrid或者是AdvanceDataGridFlex3),如果我们的itemRenderer效率低下,那么整个系统的性能将大受影响。这里列出几个比较好的建议:

  1. 尽量少用itemRenderer,这个没什么说的,能不用的尽量别用。
  2. 不要频繁的更改itemRenderer的风格change style。也就是很多人喜欢的setStyle(‘’,’’),比如更具数据变化背景颜色之类的,其实这个是很要命的,数据量小没什么感觉,数据量大了,效果就出来了。这个我在之前的文章也提到过这一点。其实可以有其他方法替换,后面详细讲。
  3. 尽量不要用容器Cantainer作为itemRenderer的基类。也就是我们常用的HBoxVBox,我的建议是宁愿用Canvas也不要用前者。至于原因将起来就复制一些。如果对高级flex开发人员来讲,我们应该尽量用UIComponent,作为基类,也就是所有界面元素的父类。

不用setStyle方法的替代法

这里有个很好的例子,就是根据所在列的数据来变更具体要显示的控件,以此来达到变换背景色的目的。

<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>

这种方法可比setStyle来得快多了,但是在程序设计上稍显麻烦。

这里还需要注意的几点:

  • 避免把风格和数据进行绑定,数据随时在变, style 也随时在变的话可以想想它的性能。
  • 采用 Canvas 或者继承 ListItemRenderer 来作为 itemRenderer 的主容器,这样便于你自己对各个空间进行控制

另外如何采用UIComponent作为itemRenderer的容器基类,有兴趣的朋友可以参考原文,这里不做翻译和解释,原文其实讲的很明白了。

from: http://wmcai.blog.163.com/blog/static/48024200831833343734/


扩展 UIComponent

目前编写 itemRenderer 最有效的方式是使用 ActionScript 类扩展 UIComponent。您可以全面控制代码,并且渲染器也可以尽可能高效。

从上例切换样式开始,编写一个扩展 UIComponent 的简单 itemRenderer。

package renderers {?import?mx.controls.listClasses.IListItemRenderer;?importmx.core.UIComponent;?public?class?PriceItemRenderer?extends?UIComponent?implementsIListItemRenderer {?function?PriceItemRenderer() { super(); } } }

您会发现我不仅编写这个类来扩展 UIComponent,还由它实施 IListItemRenderer 接口。这样做是有必要的,因为 List 控制将需要任何渲染器实施该接口,否则您会收到运行时错误,因为列表尝试将渲染器转换为该接口。

如果阅读 IListItemRenderer 的相关文档,您会发现这是一个许多其他接口的集合,UIComponent 会为您实施其中的大多数。但有一个 IListItemRenderer 扩展的接口是 UIComponent 不实施的:IDataRenderer。这需要您添加代码,为 itemRenderer 类提供您一直使用的?data?属性。

如果您尝试不实施 IDataRenderer 就使用这个类,则编译代码时会收到以下错误:

  • 1044:类 renderers:PriceItemRenderer 未实施名称空间 mx.core:IDataRenderer 中的接口方法 get data。

编辑这个类并将它更改为以下内容:

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()。这很重要,因为更改数据必须更改标签中的文本以及它们的可视性。

    function?set data(value:Object):void { _data = value; invalidateProperties(); dispatchEvent(new?FlexEvent(FlexEvent.DATA_CHANGE)); }

    调用?invalidateProperties()?会告知 Flex 框架在适当的时间调用 commitProperties() 函数。

  3. 覆盖?createChildren()?并创建标签,添加它们以显示组件列表。注意,除了创建标签外,还会设置它们的样式和?visible?属性。

    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?进行这类更改,如果您喜欢,也可以在这个类中那样做。

    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 大小匹配即可。

    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 的更多相关信息。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读