Flex Mobile Development: pay attention to list.itemRenderFunction

A colleague of mine who is building a Flex mobile application had some performance issues with a list. In short, when he used a pretty heavy custom item renderer (with checkboxes, buttons, and labels) the scrolling performance dropped a lot. When using just a label item renderer everything worked well.

So, we started to debug the code and, as I suspected, the culprit was the layout manager: the virtualization was off.

This was strange as he didn’t turn off the useVirtualLayout flag anywhere in the code – at least not explicitly. So why was the virtualization off? Because he used list.itemRenderFunction to change the item renderer at runtime. If you take a look at the documentation you will find this:

Function that returns an item renderer IFactory for a specific item. You should define an item renderer function similar to this sample function:

function myItemRendererFunction(item:Object):IFactory

Currently, when using itemRendererFunction with a virtual layout (useVirtualLayout=true), item renderer recycling is turned off. Because of this, using itemRendererFunction can cause a performance degradation and is not recommended for mobile. This may be fixed in future versions of Flex.

So, if you use a heavy item renderer and/or you have many items, don’t set the item renderer using the itemRendererFunction method.

Instead, you can wrap your custom item renderer in a ClassFactory object and then assign this object to the list.itemRenderer property. Like this:

var factory:ClassFactory = new ClassFactory(MyCustomItemRenderer);
// set the properties for custom item renderer
factory.properties = {iconField:"thumbnailSmall",
                  messageField:"description", iconHeight:180, iconWidth:180};
// set the ClassFactory object as the list item renderer
myList.itemRenderer = factory;

There is one more thing. In the example above I used the properties property of the ClassFactory object to set the properties I needed (for example what data property should be used for the message label). You can’t use this approach for setting CSS properties like fontSize. The only solution I found so far is to create setters that behind the scenes are doing something like this:

public class MyCustomItemRenderer {
   //...

   public function set fontSize(value:int):void {
      setStyle("fontSize", value);
   }

   //...
}

This was my tip of the week. And don’t forget, stay away from useVirtualLayout = false;

9 thoughts on “Flex Mobile Development: pay attention to list.itemRenderFunction

  1. Thanks so much for posting this, I had actually given up on flex as a mobile platform because of this issue. As a direct result, I moved to the corona SDK and to be honest, quite like it.

    One of the first flex mobile projects i was doing involved a large and complex scrollable list, this list was performing so badly that I thought “If a list performs this poorly, how is it going to cope with the rest of my application??”

    I feel Adobe have really dropped the ball on this, I wonder how many others have abandoned flex mobile due to performance issues, which are in fact solvable …..

    This kind of thing should create a warning in flex, for me it was a show stopper. Literally.

  2. Elliot, I think you over reacting a little bit. It is true that the tool doesn’t warn you with a compile warning. However, Flash Builder has tool tip support and displays the AS Doc that warns about this behavior.

    cheers,
    Mihai

  3. If you are interested in learning more about optimizing item renderers for scrolling lists in mobile Flex you may find my 360|Flex presentation “Deep Dive into Flex Mobile Item Renderers” helpful. Here is a link to the slides and sample code: http://jasonhanson.com/360flex/

  4. Try Greensock’s new BlitMask with ThrowProps. I’m creating very smooth lists now with it. I’m assuming here that you can use it with Flex.

  5. “There is one more thing. In the example above I used the properties property of the ClassFactory object to set the properties I needed (for example what data property should be used for the message label). You can’t use this approach for setting CSS properties like fontSize. The only solution I found so far is to create setters that behind the scenes are doing something like this:”

    Or just create your own little ClassFactory that supports styles…

    package ws.tink.mx.core
    {
    import mx.core.ClassFactory;

    public class ClassFactory extends mx.core.ClassFactory
    {

    public var styles:Array = null;

    public function ClassFactory(generator:Class=null)
    {
    super(generator);
    }

    override public function newInstance():*
    {
    var instance:Object = super.newInstance();

    for each( var p:Object in styles )
    {
    instance.setStyle( p.name, p.style );
    }

    return instance;
    }
    }
    }

  6. Pingback: Cool Stuff with the Flash Platform - 8/30/2011 | Remote Synthesis

Leave a Reply

Your email address will not be published. Required fields are marked *