1
votes

Here's the issue: I've got the list with some dataProvider and itemRendererFunction. I had to decide to use itemRenderFunction because we need to have different renderers for different items in dataProvider. The problem is that when single item in dataProvider changes, I have to refresh whole dataProvider, which is quite problematic in case of big amount of data. Is there any way to refresh a single item in this case?

Example code:

<?xml version="1.0" encoding="utf-8"?>
<s:Application name="list_test"
               xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               click="onApplicationClick(event)"
               >

    <fx:Script>
        <![CDATA[
            import mx.core.ClassFactory;

            import renderers.*;

            import spark.skins.spark.DefaultItemRenderer;

            private function itemRendererFunction(item:Object):ClassFactory
            {
                var rendererClass:Class = DefaultItemRenderer;
                switch (item.type)
                {
                    case "typeA":
                        rendererClass = ItemRendererTypeA;
                        break;
                    case "typeB":
                        rendererClass = ItemRendererTypeB;
                        break;
                    default:
                        break;
                }
                return new ClassFactory(rendererClass);
            }

            protected function onApplicationClick(event:MouseEvent):void
            {
                var item:Object = dp.getItemAt(0);
                item.type = "typeB";
                dp.itemUpdated(item);
                dp.refresh();
            }

        ]]>
    </fx:Script>
    <fx:Declarations>
        <s:ArrayCollection id="dp">
            <fx:Object name="Item 1"
                       type="typeA"
                       />
            <fx:Object name="Item 2"
                       type="typeA"
                       />
            <fx:Object name="Item 3"
                       type="typeB"
                       />
        </s:ArrayCollection>
    </fx:Declarations>
            <s:List id="list"
                    labelField="name"
                    itemRendererFunction="itemRendererFunction"
                    horizontalCenter="0"
                    verticalCenter="0"
                    useVirtualLayout="true"
                    height="300"
                    dataProvider="{dp}"
                    >
            </s:List>
</s:Application>

I've placed some traces on addToStage event handlers in item renderers classes. All of them are called at every single click.

1
Can you move the "typeA" vs. "typeB" logic into the item renderer? Write an override for the data setter in the renderer that examines "data.type" -- then you could set a state or toggle a component's visibility.Brian
Thank you for response Brian. That was the initial solution which we had to drop. The issue is, let's say, "typeB" needs very big and complicated renderer. This object is far too big to use it more than once in the list.pikar

1 Answers

2
votes

As discussed in this SO post, you'll want to avoid returning a new instance of ClassFactory for every invocation of your itemRendererFunction:

    private var itemRendererTypeA:ClassFactory = new ClassFactory(ItemRendererTypeA);
    private var itemRendererTypeB:ClassFactory = new ClassFactory(ItemRendererTypeB);

    private function itemRendererFunction(item:Object):ClassFactory
    {
        switch (item.type)
        {
            case "typeA":
                return itemRendererTypeA;
                break;
            case "typeB":
                return itemRendererTypeB;
                break;
            default:
                break;
        }
    }