Search code examples
actionscript-3apache-flexactionscriptflex4

Is it possible to refresh a single itemRenderer without refreshing whole dataProvider?


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.


Solution

  • 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;
            }
        }