Please read the discussion about memory leak here.
I think I found the workaround for this issue. We need to override the set columns method in a extended ADG class and add the code to free the dictionary holding on to the itemRenderers. Here is the code.
<?xml version="1.0" encoding="utf-8"?>
<mx:AdvancedDataGrid xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
override public function set columns(value:Array):void
{
super.columns = value;
itemRendererToFactoryMap = new Dictionary(false);
}
]]>
</mx:Script>
</mx:AdvancedDataGrid>
I have added two polls to the end of my blog. One for suggesting in what areas should ADG performance improve. Second one for overall performance of ADG in your projects/apps.
Please spare some time out of your busy schedule and take the polls.
I would urge you take both the polls because just taking one poll many not deliver the exact picture. For example if you say vertical scrolling performance needs to be improved we don't know whether the app is hurt by its performance or it is that it would do better with a performance boost.
Thanks for your time !
Of-course if you would like to send me a sample showing poor performance in a particular/general context please do by sending a mail
Update:I am seeing more number of votes on Bad than expected :(
I would appreciate if you leave a comment as to which particular area of ADG you found the performance to be so poor that it forced you turn it down. I am asking this because votes are also going in favor of Good and OK. It would be of great help if I get a pointer in that direction so that we can study that area of the code more and see what performance improvements can be done. Thanks!
What I thought is a known fact seems not so widely known. Hence posting it.
When FlexBuilder Pro version is bought and a valid licensce key is entered the source code for the complete datavisulation.swc would get unzipped and get placed under
directory. Which means users would get access to AdvancedDataGrid, Charts and OLAP source code.
It is not open-source but source is available for you to take a look and override functions with more confidence and knowledge of the internal workings. And of-course suggest/complain !
Here is a sample I wrote using GC to group mails according to Date and Subject very similar to Outlook. This sample serves to show the complex ways in which GC can be configures and used.
Subject grouping: The sample uses GroupingField.groupingFunction and GroupingField.compareFunction to achive the Subject grouping even when subject line text is prefixed with RE:, FW: etc. Grouping.groupingObjectFunction is used to supply a custom grouping object MailGroup which has a date field getter function to return the maximum date of the child mail items.
Date grouping: Again groupingFunction is used to form diffrent groups of mails based on the date value.
The "show unread mails" option can be used to remove the read mails from the view. This shows filtering applied to the HierarchicalCollectionView which ADG creates internally when a GroupingCollection (or anything which implements IHierarchicalData) is supplied as the dataProvider.
The "highlight unread mails" option uses the ADG.styleFunction property to hightlight the unread mails by making them bold.
Changing the row backgroundColor in AdvancedDataGrid to highlight few rows is easy (though not possible out of the box).
I have used a different approach than overriding the drawRowBackground function used for DG. The drawback of this approach is that the selection feedback gets almost hidden by the background coloring. If the intention is to highlight a search or hightlight a particular values this should not be a serious problem.
The default itemRenderer ADGItemRenderer extends from UITextField (for perforamnce reasons) which doesn't have a backgroundColor style. Hence it is not possible to do it out of the box. But TextField (parent of UITextField) has background and backgroundColor properties which can be set to change the backgroundColor of the TextField.
I have created a new custom itemRenderer ADGItemRendererEx which derives from ADGItemRenderer. I have added a "rowColor" style to this and use this style value to set the TextFields background color.
By providing a styleFunction to ADG we get control to return any styles we want to be set on the itemRenderer. Any logic to determine a particular rows color can go into this function. The return value is a object with style names as properties and style values as proprety-values. For ex:
return { rowColor:0xFF0000, fontWeight:"bold" };
If function logic decides not to change the styles it can return an empty object.
The following sample shows the result. By typing any string in the text box the particular row containing the searched string is highlighted. User can choose to search for either company column or product column.
and feed into DG or ADG it won't create columns auto-magically as it does for Object data type. This may be because it is difficult to decide whether you want to display the child nodes as columns or attributes of nodes. And may be it was not appropriate to clutter the API with one more flag to do this.
I wrote the following code to get this working.
private function generateCols(input:XMLList,
useAttributes:Boolean = false):Array
{
var e1:XML = input[0];
var columns:Array = [];
var children:XMLList ;
if (useAttributes)
children = e1.attributes();
else
children = e1.children();
for each(var child:XML in children)
{
var col:DataGridColumn = new DataGridColumn();
col.dataField = useAttributes ? "@" + child.name() : child.name();
var fieldName:String = child.name();
col.headerText = fieldName.charAt(0).toUpperCase() + fieldName.substr(1);
columns.push(col);
}
return columns;
}
The AdvancedDataGrid control can be configured and used as a simple Tree control with sorting support (which is not available in the Tree control).
The following example shows how.
When hierarchical XML (or Object based) data is fed into a HierachicalData (which implements IHierachicalData) and set as dataProvider to ADG it internally converts it into a HierarchicalCollectionView (implementing IHierarchicalCollectionView). The good news is that HierarchicalCollectionView provides the sort and filtering APIs which can be used to sort and filter the data very similar to flat data.
Click on the "Simple sort" button to see how the data gets sorted recursively. It doesn't do a good job as it mixes up parent and leaf items. If you are one those who expects everything according to the alphabetical order you may like it !
Click on the "Custom sort" button to see how the sorting can be customized to show the parent items at the top and leaf items at the bottom. The custom sort function uses the IHierarchicalData.canHaveChildren API to move the parent items up the ladder.
I have seen numerous questions regarding how to specify DataGridColumn.dataField when the data is nested (object or XML). Developers attempt to use "datafield1.datafield2.datafield3" to find out that it doesn't work !
The data might look like this :
<mx:XMLList id="testData" xmlns="">
<root>
<item>
<childItem>
<name>India Flex group</name>
<mail>indiafx@gmail.com</mail>
</childItem>
<location>India</location>
</item>
<item>
<childItem>
<name>Singapore Flex group</name>
<mail>singaporefx@gmail.com</mail>
</childItem>
<location>Singapore</location>
</item>
<item>
<childItem>
<name>Sreenivas</name>
<mail>sreenivas.ramaswamy@gmail.com</mail>
</childItem>
<location>Bangalore</location>
</item>
</root>
</mx:XMLList>
The answer has always (most of the time?) been to use DataGrid.labelFunction. I dislike the solution because it requires the developer to do this again and again for every column and every usage. I find it easier to extend the DataGridColumn and override the itemToLabel function to do the needful.
The usage is simple. The Nested and ordinary columns can be mixed or only nested columns can be used as the logic kicks in only when "." is present in dataField value.
Both of them speak about data editing/update not getting propagated properly through a ArrayCollection. The samples are using the ArrayCollection available from the HTTPService result directly. The HTTPService is creating the ArrayCollection first and then updating its source Array with items. The Array object doesn't dispatch any events when it is updated with new items. Due to this ArrayCollection has no way of adding event listeners for property changes to the items added later on. Hence the changes are detected only for the items present at the time of creation of ArrayCollection which happens to be 2 items.
If one desire to use the HTTP result as dataProvider and expects data updates to get properly propagated they need to create a new ArrayCollection using the source of the default ArrayCollection present in the HTTP result.
data_provider = new ArrayCollection(ArrayCollection(srv.lastResult.data.result).source);
where srv is the HTTPService. If data_provider is already a ArrayCollection then we can just modify the source as follows
This bug exists in Flex 2 and may not be fixed in Flex 3 as the current bug status is deffered!
The source is available here and data getting loaded here.
It is possible to generate custom groups using groupingFunction property of GroupingField. Take a look at the following sample. By choosing different options from "Choose age range" users can view the same data in different groups.
The sample uses fictitious data of web site visitors by age and location. The example uses COUNT summary option to show how many visitors exist in each group.
The only thing to remember while writing a groupingFunction is that the return value should not change the sorting order being used for the dataField. Another way to put it is, the groupingFunction should return group names in a sorted order only. It shouldnot return group names in a random fashion.
Using a XMLList as source for GroupingCollection or HierarchicalData is a bit tricky. The trickiness comes from the fact that there are two ways to specify values for a XML node. One as attributes and second as child nodes. Depending on which way values are specified we need to set properties differently to get the desired display in ADG.
For XMLList data type HierarchicalData treats the child nodes of a node to be children of the parent node by default.
Specifying values as attributes:
If above data is set as source to HierarchicalData it would treat field1, field2 and subnodes as children of Parent node, which is not correct. To tell HierarchicalData to use only the nodes under subnodes as children set HierarchicalData.childrenField to "subnodes".
The same rules apply when GroupingCollection (which is derived from HierarchicalData) is used to group flat data.
Suppose following data is used as input to GroupingCollection and grouped on Region
The result won't get displayed because the base HierarchicalData would treat <Region>, <Territory> etc nodes also as children of Row. To get proper display we need to set GroupingCollection.childrenField="abc" or some non existent node name. This would cause HierarchicalData to report that no children exist for the Row.
From the poll conducted I find that many users want Smart column width based on data displayed in DG/ADG.
I hope people requesting this feature know that it is a CPU intensive process to go over all the items in the dataProvider to find out maximum width required for all the columns. If the number of visible columns is more it would take even more time to compute the values and layout the columns.
If a labelFunction is being used at DG or DGColumn level and custom styles have been used on a column for fontSize for example, it complicates the computation even more.
When the data is being paged from a server it is not possible to compute the smart width at all without requesting all the data from the server, which is never desirable.
Keeping these things in mind I feel it makes sense to have a flag on individaul DGcolumn (apart from one on the DG itself) to control the computation of smart width. If the flag is true width is computed and false would use the normal way of determining the column width.
This example shows how GroupingCollection can be used to generate summary data for flat data and AdvancedDataGrid can be used to display the result.
The trick (or dirty work around if you like to call it so) is to generate a single dummy group using a invalid grouping field. The summary we require is specified as usual using the SummaryRow and SummaryField.
When this GroupingCollection is fed to ADG.dataProvider it would try to display in a tree view. By setting the HierarchicalCollectionView.showRoot flag to false to avoid displaying the single group parent.
By specifying the default ADGItemRenderer as ADG.groupItemRenderer we can prevent the group icons from getting displayed.
By using the ADG.groupLabelFunction property one can customize the group label displayed for the group nodes.
The following example shows how children count can be displayed as part of the group label when the group is closed.
The source can be found here.
I created three polls at the end of my blog. One to know how users are feelling about ADG in its current form, second what features of ADG in Flex 3 users are liking the most and third one to see what new features users would like to see in the next version of AdvancedDataGrid to make it more useful.
Who knows you may be able to guide the future developement of ADG !
Thanks in advance for giving your opinion!
If you want to see more choices do leave a comment. I would add it.
In Flex 3 Beta-2, GroupingCollection adds support for asychronous refresh. When we have large number of input rows or don't want to wait for the grouping to finish to see the results we can pass true to GroupingCollection.refresh(async:Boolean) and get to view the results as the grouped data is built. Users are allowed to interact with the shown information. Refresh can be even stopped by calling cancelRefresh.
I wrote a small app to test this. The app generates random data and displays it in AdvancedDataGrid(ADG) when "Populate ADG" is clicked. The number of data rows can be modified using the numeric stepper. A click on "Group" starts async refresh and ADG starts displaying the results immediately. Grouping can be cancelled any time using "Cancel Grouping". The three check boxes allow different combinations of grouping to be performed.
Option to pause/resume a refresh is not available.
Using charts as itemRenderers in DG and ADG is easy. Find the sample files here
The sample uses a LineChart as itemRenderer for the third column and a PieChart in the child area. The column-spanning option available through RendererProviders is used to make the PieChart occupy the whole row.
The sample shows use of HierarchicalData but even without that All chart types can be used as itemRenderes.
Customizing headers in DataGrid and AdvancedDataGrid (DG/ADG) is very easy. Just point the headerStyleName property available on these controls to any style declaration you want. The following image shows one such example where the header text is colored in blue and red. The second column text is center aligned.
The important thing to notice here is that the headers are now styled differently than the column content. If the same styles were set on the column objects then the header as well as column content would have got same styles. headerStyleName allows customizing only the headers.
The headerStyleName is available on the control and the column object. Hence you can set the control.headerStyleName to customize all the headers and use the column.headerStyleName to customize individual headers.
A sample mxml file.
I improved my previous sample with column grouping getting the following look.
The new MXML can be found here.
One problem I immediately noticed is that one cannot horizontally center the headerText of the columns without centering the column cell text, this is specially a problem with first column. I filed a request for this.
The headerText cannot be vertically centered either. However this has been already reported requesting even more options.