Using the callLater() method

The callLater() method queues an operation to be performed for the next screen refresh, rather than in the current update. Without the callLater() method, you might try to access a property of a component that is not yet available. The callLater() method is most commonly used with the creationComplete event to ensure that a component has finished being created before Flex proceeds with a specified method call on that component.

All objects that inherit from the UIComponent class can open the callLater() method. It has the following signature:

callLater(method:Function, args:Array):void

The method argument is the function to call on the object. The args argument is an optional Array of arguments that you can pass to that function.

The following example defers the invocation of the doSomething() method, but when it is opened, Flex passes the Event object and the “Product Description” String in an Array to that function:

callLater(doSomething, [event, "Product Description"]); 
... 
private function doSomething(event:Event, title:String):void { 
    ... 
}

The following example uses a call to the callLater() method to ensure that new data is added to a DataGrid before Flex tries to put focus on the new row. Without the callLater() method, Flex might try to focus on a cell that does not exist and throw an error:

<?xml version="1.0"?>
<!-- layoutperformance/CallLaterAddItem.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark"
    initialize="initData()">

    <fx:Script><![CDATA[
        import mx.collections.*;
        private var DGArray:Array = [
            {Artist:'Pavement', Album:'Charred Walls', Price:11.99},
            {Artist:'Pavement', Album:'Good For You', Price:11.99}];
            
        [Bindable]
        public var initDG:ArrayCollection;
        //Initialize initDG ArrayCollection variable from the Array.
        
        public function initData():void {
            initDG=new ArrayCollection(DGArray);
        }
        
        public function addNewItem():void {
            var o:Object;
            o = {Artist:'Pavement', Album:'Tradio', Price:11.99};
            initDG.addItem(o);
            callLater(focusNewRow);
        }

        public function focusNewRow():void {
            myGrid.editedItemPosition = { 
                columnIndex:0,rowIndex:myGrid.dataProvider.length-1
            };
        }
        
    ]]></fx:Script>

    <s:VGroup>
        <mx:DataGrid id="myGrid" width="350" height="200" dataProvider="{initDG}"  editable="true">
            <mx:columns>
                <fx:Array>
                    <mx:DataGridColumn dataField="Album" />
                    <mx:DataGridColumn dataField="Price" />
                </fx:Array>
            </mx:columns> 
        </mx:DataGrid>

        <s:Button id="b1" label="Add New Item" click="addNewItem()"/>
    </s:VGroup>
    
</s:Application>

The executing SWF file for the previous example is shown below:

Another use of the callLater() method is to create a recursive method. Because the function is called only after the next screen refresh (or frame), the callLater() method can be used to create animations or scroll text with methods that reference themselves.

The following example scrolls ticker symbols across the screen and lets users adjust the speed with an HSlider control:

<?xml version="1.0"?>
<!-- layoutperformance/CallLaterTicker.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">
    
    <fx:Script><![CDATA[
    
        [Bindable]
        public var text:String = "SLAR:95.5....TIBA:42....RTF:34.15....AST:23.42";
        [Bindable]
        public var speed:Number = 5;

        public function initTicker():void {
            theText.move( this.width+10, 0 ); // Start the text on the right side.
            callLater(moveText);
        }

        public function moveText():void {
            var xpos:Number = theText.x;
            if( xpos-speed+theText.width < 0 ) {
                xpos = this.width+10; // Start the text on the right side.
            }
            xpos -= speed;
            theText.move(xpos,0);
            callLater(moveText);
        }

        public function changeSpeed():void {
            speed = speedSelector.value;
        }
        
    ]]></fx:Script>

    <s:Panel title="Ticker Sample" width="400" height="200">
        <s:VGroup>
                <mx:Canvas creationComplete="initTicker()"
                    horizontalScrollPolicy="off" backgroundColor="red" color="white"
                    width="400">
                <mx:Label id="theText" text="{text}" y="0"/>
            </mx:Canvas>
            <mx:HBox>
                <mx:Label text="Speed:"/>
                <mx:HSlider minimum="1" maximum="10" value="{speed}"
                    id="speedSelector" snapInterval="1" tickInterval="1"
                    change="changeSpeed()"/>
            </mx:HBox>
        </s:VGroup>
    </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below: