Recently, while working with a customer on optimizing some performance issues, we came across a scenario, where the customer wanted to rapidly update the grid with new data coming from the server. This is a rather complicated use case to accomodate, since the default behavior of the grid is to rebuild itself in response to additions, deletions etc in the dataprovider. It also is quite resource intensive to do so, because usually additions or deletions means you have to rebuild the sort, rerun all filters, update page indexes, and a lot of internal cached information that makes the grid extremely performant needs to be rebuilt. 

We already have the TraderView example that demonstrates how to respond to rapid updates. We do this by turning off the rebuildGridOnDataProviderChange flag, which basically means grid will not respond to changes in dataprovider, and instead will depend on you to explicitly ask it to update via either the rebuild() method or the rebuildBody method. However, in that example, we simlpy call targeted refresh cell calls, to update specific cells that need to be updated. This makes it possible for the grid to respond to a numerous updates per second.

However, keep in mind that with updates to the rows already drawn, there is no need to rebuild the internal index (unless ofcourse, you want to sort, which means you will need to rebuild the index). Basically the caveat to keep in mind is that both for insert and updates, if you want to sort, page, or filter again, there is no way to consume a large number of such operation in subsecond time frames. And this is not a limitation of the grid, but just the amount of time it takes to sort, filter and page an array (even without a grid involved) make it prohibitively expensive to perform this operation multiple times a second.

This brings us to the actual implementation of this use case. Since for this customer, we are inserting rows at the top (as new data comes in, it pushes everything else down), it makes it a lot easier, since we simply do the same thing that the grid would have done, that is, update the index. 

Lets take a quick look at the code that does this:

protected function insertTimerHandler(event:TimerEvent):void

                  {

                        fdg.rebuildGridOnDataProviderChange=false;//so we dont rebuild the index when we change the dataprovider

                        var chg:Number=getRandom(-10,10);

                        //we add it to the dataprovider, this should not affect the grid.

                        //we are adding at index 0

                        var newStock:Object={"id":stocks.length,"symbol":"NEW TICK" + stocks.length, "name":"NEW Ticker with symbol"+stocks.length

                              ,"last":getRandom(20,30),"change":chg+"%","tickUp":(chg>0)};

                        stocks.addItemAt(newStock,0);

                       

                        var rowPos:RowPositionInfo = new RowPositionInfo(

                              newStock,//the data object

                              0, //row index of the data object (0 because we are adding it at the top, you can add it anywhere

                              0,//vertical position of the data object (rowIndex * rowHeight) assuming no variable row height. Or you could lookup the verticalPos of the item above me, and add his height to that number to get this number

                              fdg.rowHeight,//same height rows. For variable row height, you can calculate this

                              fdg.columnLevel, //the top level. If you are adding a child object, you can use the appropriate inner level

                              RowPositionInfo.ROW_TYPE_DATA //type of row. For inner level rows, you can add Header, footer, filter, pager ,renderer rows

                              );   

                        for each(var existingRowPos:RowPositionInfo in fdg.bodyContainer.itemVerticalPositions)

                        {

                              existingRowPos.rowIndex +=1;

                              existingRowPos.verticalPosition += fdg.rowHeight;//push everything down.

                        }

                        for each(var row:RowInfo in fdg.bodyContainer.rows){

                              //now go through all the drawn rows, and update their y property

                              row.y=row.rowPositionInfo.verticalPosition;

                        }

                        fdg.bodyContainer.itemVerticalPositions.splice(0,0,rowPos);//add item at index 0.

                        fdg.bodyContainer.recycle(fdg.columnLevel,false,fdg.rowHeight,false);//now make sure the body draws the row

                        fdg.bodyContainer.placeComponents();//update the cell positions

                        if(stocks.length%5==0){

                              //this will paint the cell background

                              //this is very slighty heavier than other methods, so dont call it as frequently.

                              //may be call it every 2 seconds or so

                              fdg.bodyContainer.invalidateCells();

                        }

                  }

 

                 

 

Here is the sample :

 

TraderView.mxml (9.67 kb)

 

And here is the screenshot: