Not yet rated

Problem

Created a GroupingCollection object which has a flat ArrayCollection as it's source. Assigned this GroupingCollection as dataProvider to a dynamically created AdvancedDataGrid. In the next statement tried to display length of the dataProvider which lead to a Null Pointer Exception. Code for the problem is in the 'detailed explanation' section:

Solution

Normally, using the validateNow() method would work to update the dataProvider. But, when we are dynamically adding a component, it is important to note that validateNow() can only be used after the component has been added to the layout.

Detailed explanation

Code demonstrating the problem:

{
   var myADG:AdvancedDataGrid = new AdvancedDataGrid() ;
   var grpColl:GroupingCollection = new GroupingCollection() ;
   grpColl.source = FlatCollection ;     // where FlatCollection is
an ArrayCollection
   myADG.dataProvider = grpColl;
   trace("Length of DataProvider at this line is: " +
   myADG.dataProvider.length) ;   //leads to Null pointer
   Exception
   this.addChild(myADG);
}

Sometimes flex components don't update the change in property immediately. 
Processing properties that require substantial computation are sometimes not processed until the script finishes executing. As an example, think of layout properties like height and width. Changing the height property may require recalculation of height of parent and children containers. The script may change the height property more than once, so it makes sense to delay the update till later.
So in cases like these, instead of updating the property, the components call one of the LayoutManager's (ILayoutManager.as) invalidate methods and apply the properties at a later time.
But there may be cases when the user needs to update the property immediately as is the case here. To do that we can use the vaidateNow() method. But this may not be the end of the problem. Take a look at the code below:

{
   var myADG:AdvancedDataGrid = new AdvancedDataGrid() ;
   var grpColl:GroupingCollection = new GroupingCollection() ;
   grpColl.source = FlatCollection ;     // where FlatCollection is
an
   ArrayCollection
   myADG.dataProvider = grpColl;
   myADG.validateNow();                      //should update the
dataProvider
   trace("Length of DataProvider at this line is: " +
   myADG.dataProvider.length) ;
   //still leads to Null pointer Exception
   this.addChild(myADG);
}

The above code would still lead to a Null Pointer Exception.
To know the reason let us talk a little more about the LayoutManager mentioned above.
The LayoutManager is the engine behind Flex's measurement and layout strategy. Layout is performed in three phases; commit, measurement, and layout.
Each phase is distinct from the others and all UIComponents of one phase are processed prior to moving on to the next phase.
The respective methods for performing these three steps are:
· validateProperties()
· validateSize()
· validateDisplayList()

When execution of these methods needs to be deferred as discussed above, the following three functions are executed instead:
· invalidateProperties()
· invalidateSize()
· invalidateDisplayList()

These methods when called put the calling object in a list of objects which want to call their validate counterpart later.
Calling validateNow() forces the first three functions to be executed, updating all these three properties with other properties that validateNow() updates.
But when we call validateNow() in the code above, we have not added the AdvancedDataGrid to the Application (so it is not part of the layout). So we are in the code trying to validate properties (height, width etc) which might not even exist at this point.
If instead we call validateNow() after adding the grid to the layout, it is able to execute normally, updating the dataProvider.
 

{
    var myADG:AdvancedDataGrid = new AdvancedDataGrid() ;
    var grpColl:GroupingCollection = new GroupingCollection() ;
    grpColl.source = FlatCollection ;     // where FlatCollection
is an
ArrayCollection
    myADG.dataProvider = grpColl;
    this.addChild(myADG);
    myADG.validateNow();                      //updates the
    dataProvider
    trace("Length of DataProvider at this line is: " +
    myADG.dataProvider.length) ;
    //displays correct value of length
}


 


+
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

Report abuse

Related recipes