2

我试图找出一种方法来提高其中包含项目渲染的组合框的性能。当我使用没有自定义项目渲染器的组合框时,下拉菜单会快速打开,并且组合框的响应速度非常快。当我添加一个简单的项目渲染器时,现在需要一秒钟才能打开组合框。这就像它创建所有孩子然后缓存它们。之后,组合框打开正常,直到您选择一个项目。然后打开组合框也需要一段时间。

这是一个演示该问题的示例应用程序:

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
            height="100%" width="100%" xmlns:local="*"
    >
<mx:Script><![CDATA[
    import mx.collections.ArrayCollection;

    public var dataProvider:ArrayCollection = new ArrayCollection(
               [{label:"test1"}, 
                {label:"test2"}, 
                {label:"test3"}]);

    ]]></mx:Script>

<!-- combobox with item renderer, this has a delay when opening -->

<mx:ComboBox width="200"
             dataProvider="{dataProvider}">
    <mx:itemRenderer>
        <mx:Component>
            <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
                <mx:Label text="'item renderer' + {data.label}"/>
            </mx:HBox>
        </mx:Component>
    </mx:itemRenderer>
</mx:ComboBox>

<!-- default combobox, this works fine -->

<mx:ComboBox width="200"
             dataProvider="{dataProvider}"/>
</mx:Application>

我在这里想念什么?这似乎不应该发生。

4

2 回答 2

4

在花了一些时间试图找到解决方案后,我发现如果在 中只定义一个“干净”的子组件<mx:Component>,性能会好得多。

因此,以下提供了良好的性能:

<mx:Component>
    <mx:HBox /> ( "clean" )
</mx:Component>

而这个表现不佳(延迟):

<mx:Component>
    <mx:HBox>
        <mx:Label /> ( not "clean" )
    </mx:HBox>
</mx:Component>

为了解决这个问题,我们可以使用代码创建子组件:

<mx:itemRenderer>
    <mx:Component>
        <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
            <mx:Script>
                <![CDATA[
                    import mx.controls.Label;

                    // Define the label instance
                    private var lbl:Label = new Label();

                    // Add the label as a child component
                    override protected function createChildren(): void {
                        super.createChildren();
                        addChild( lbl );
                    }

                    // Set the data
                    override public function set data( value:Object ): void {
                        super.data = value;
                        if ( value ) {
                            lbl.text = value.label;
                        }
                    }
                ]]>
            </mx:Script>
        </mx:HBox>
    </mx:Component>
</mx:itemRenderer>

演示:https ://github.com/jeantimex/flex-combobox-itemrenderer

希望有帮助!

于 2012-10-05T22:07:55.990 回答
3

这可能是朝着正确方向迈出的一步;但我不能保证有解决方案。我建议您首先重写您的 itemRenderer 以不使用绑定。通过教他们,我已经为付费客户解决了很多内存泄漏问题。在 itemRenderers 中,Binding 也是一项性能繁重的操作;所以我建议将其从操作中删除。

我更喜欢响应 dataChange 方法,而不是在 itemRenderer 中使用 Binding。

我还建议您从 itemRenderer 中删除 HBox;因为您应该能够按原样使用标签:

<mx:ComboBox width="200"
             dataProvider="{dataProvider}">
    <mx:itemRenderer>
        <mx:Component>
            <mx:Label dataChange="onDataChange(event)">
              <mx:Script>
                 protected function onDataChange(event:Event):void{
                    this.text='item renderer' + data.label;
                 }
              </mx:Script>
            </mx:Label>
        </mx:Component>
    </mx:itemRenderer>
</mx:ComboBox>

我不确定这是否会解决任何性能问题。在创建 Flextras AutoComplete 时,我必须解决与 Flex ComboBox 相关的许多奇怪问题。

记忆告诉我,在 Flex 3.4(及之前)中,每次关闭下拉菜单时;它被破坏了——基本上没有缓存在内存中。这在 Flex 3.5 中发生了变化,而他们开始缓存它并重新使用相同的下拉对象。我想知道您感知的性能问题是否与此有关。


编辑1:基于对这篇文章没有解决根本问题的投诉;我根据原始海报代码和我建议的更改组合了这个测试用例。我建议的更改确实解决了原始海报所遇到的问题。以下是示例背后的来源:

    [Bindable]
    public var dataProvider:ArrayCollection = new ArrayCollection(
        [{label:"test1"}, 
            {label:"test2"}, 
            {label:"test3"}]);

]]></mx:Script>

<!-- combobox with item renderer, this has a delay when opening -->

<mx:VBox>

<!-- ComboBox provided by original poster -->
<mx:ComboBox width="200"
             dataProvider="{dataProvider}">
    <mx:itemRenderer>
        <mx:Component>
            <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
                <mx:Label text="'item renderer' + {data.label}"/>
            </mx:HBox>
        </mx:Component>
    </mx:itemRenderer>
</mx:ComboBox>


<!-- ComboBox with rewritten itemRenderer; which does not exhibit the problem -->
<mx:ComboBox width="200"
             dataProvider="{dataProvider}">
    <mx:itemRenderer>
        <mx:Component>
            <mx:Label dataChange="label1_dataChangeHandler(event)">
                <mx:Script>
                    <![CDATA[
                        import mx.events.FlexEvent;

                        protected function label1_dataChangeHandler(event:FlexEvent):void
                        {
                            this.text = "item renderer" + data.label;
                        }

                    ]]>
                </mx:Script>
            </mx:Label>
        </mx:Component>
    </mx:itemRenderer>
</mx:ComboBox>


<!-- default combobox, this works fine -->

<mx:ComboBox width="200"
             dataProvider="{dataProvider}"/>
</mx:VBox>


编辑 2:devshorts 说如果我们将组件创建为独立的 itemRenderer,我的代码将不起作用;但是我不明白为什么不。

这是独立 itemRenderer 的代码,名为 com.flextras.listRenderers.CustomLabelRenderer:

<?xml version="1.0" encoding="utf-8"?>
<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml" dataChange="label1_dataChangeHandler(event)">

    <mx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            protected function label1_dataChangeHandler(event:FlexEvent):void
            {
                this.text = "item renderer" + data.label;
            }

        ]]>
    </mx:Script>    
</mx:Label>

这里有一些代码可以添加到上面的邮件应用程序中来测试它:

<!-- ComboBox, like above with the itemRenderer as a separate component -->
    <mx:ComboBox width="200"
             dataProvider="{dataProvider}" itemRenderer="com.flextras.listRenderers.CustomLabelRenderer" />

我在我提供的链接上更新了应用程序以包含这个新的 ComboBox 实例;它现在是名单上的第 3 位。

于 2012-08-27T18:58:27.760 回答