Rendering The Fat

53
Rendering the Fat: How to Keep Your DataGrid Healthy Ben Schmidtke III Digital Primates [email protected] Twitter: stunnedgrowth

description

A look at how to create slim item renderers for large applications to keep performance up on DataGrid and AdvancedDataGrid in Flex 3.

Transcript of Rendering The Fat

Page 1: Rendering The Fat

Rendering the Fat:How to Keep Your DataGrid Healthy

Ben Schmidtke IIIDigital Primates

[email protected]: stunnedgrowth

Page 2: Rendering The Fat

Who Am I

• Ben Schmidtke III• Consultant - Digital Primates IT Consulting

Group• Flash Platform Developer for 11 years• Adobe Certified Instructor• Twitter: stunnedgrowth

Page 3: Rendering The Fat

Agenda• Overview of List Components • DataGrid and AdvancedDataGrid• Why should we take care of them• ItemRenderers• Building Slim ItemRenderers• Tips and Guidelines• Questions

Page 4: Rendering The Fat

Get To It• Focus will be looking at best practices

for dealing with custom cell formatting

• Data customization in DataGrid and AdvancedDataGrid

• Many of the concepts can be used in the other List components

Page 5: Rendering The Fat

The Interwebs

• The Internet is full of examples about how to use Flex components.

• Some are great• Some are ok• Others, let’s pretend they don’t exist.

Page 6: Rendering The Fat

Out Of The Box

• List Controls – List – Tree– DataGrid– TileList– Menu– And More…

• Data Visualization– AdvancedDataGrid– OLAPDataGrid

Flex 3 provides several components for presenting data in a list format:

Page 7: Rendering The Fat

General Features• Support Multiple Data Types• Drag and Drop• Scrolling - Vertical and Horizontal• Cell Editing• Variable Row Height• labelFunction• And more...

Page 8: Rendering The Fat

DataGrid: What Is It?• Presents data in a Table format– Rows– Columns

• Can automatically create rows & columns based on the data

• Single Column Sorting• Column Reordering

Page 9: Rendering The Fat

AdvancedDataGrid

• Supports all the functionality of DataGrid• Provides support for Hierarchical Data

– Understands how to display parent/child relationships.

– XML, XMLList, HierarchicalData, HierarchicalCollectionView

– Custom objects with “parent” and “children” properties

• Advanced Sorting (Multiple Columns)• Column Grouping

Page 10: Rendering The Fat

In Short They…

• Are a view for the data model• Can render data multiple ways– Flat, Hierarchical Data, Grouped

• Are a control that render other controls– Headers– Renderers– Editors– ScrollBars, Lines & Other UI Stuff

Page 11: Rendering The Fat

Why should we take care of it?

– Performance– Troubleshooting– Flexibility–Maintainability

Page 12: Rendering The Fat

It Takes Work• Large quantities of information• Each cell is a component• The more rows and columns

displayed decreases performance

Page 13: Rendering The Fat

What Could Go Wrong?• Cells appear slow to display• Content placed incorrectly

“sometimes work, sometimes not work”• Content shift a few pixels for no reason• Scrolling is jumpy or lag• Sorting & Column reordering take a long

time to process

• In worst case, it crashes.

Page 14: Rendering The Fat

It All Boils Down To• Unexpected Results• Poor User Experience• Cranky Client • Your Personal Health: Stress

Page 15: Rendering The Fat

The Fat : ItemRenderers

What are they?– Purpose:• Read data• Present the data (Text, Icons, Controls, etc.)

• What are they not?– Things that compute data to display–mx.containers.* (HBox, Canvas, etc.)

Page 16: Rendering The Fat

ItemRenderer Lifecycle

• In general, list components will only create as many ItemRenderers as needed to display

– 1 Column X 10 Visible Rows = 10 Renderers– 100 data objects = 10 Renderers– Plus one or two extra for performance reasons

• ItemRenderers are Recycled

Page 17: Rendering The Fat

The Default: It’s Text!• DataGrid– DataGridItemRenderer• Extends UITextField > FlexTextField >

TextField

• AdvancedDataGrid– AdvancedDataGridItemRenderer• Extends UITextField > FlexTextField >

TextFIeld

Page 18: Rendering The Fat

Why Is It Text?• Extremely lightweight• Direct and to the point• Take the least amount of time to

create and display• No container overhead

Page 19: Rendering The Fat

But Containers Are Easy…

• Containers provide a lot of useful functionality:

– Automatic Layout: Horizontal & Vertical– Absolute Layout: Coordinates X and Y– Scrollbars– Dividers, Tabs, etc.

Page 20: Rendering The Fat

Too Much Functionality

• Containers are performance heavy

• Everything that makes them easy, slows them down

• 10 Rows + 10 Columns = 100 Containers

Page 21: Rendering The Fat

Custom ItemRenderersDepending on the project

requirements, it most likely require a custom ItemRenderer

– Different text colors based on the data– Support for icons– Support for other Controls• CheckBox, ComboBox, etc.

Page 22: Rendering The Fat

Do you need one?

• If you do not need one, do not create one

Custom String Manipulation– Use a label function if possible– Can be done with out creating a

renderer

Page 23: Rendering The Fat

Typical Label Function

public function myLabelFunction(item:Object, column:DataGridColumn):String

{return item.firstName + " " + item.lastName;

}

<mx:DataGrid dataProvider="{myDataProvider}"><mx:columns>

<mx:DataGridColumn labelFunction=“myLabelFunction"/></mx:columns>

</mx:DataGrid>

Page 24: Rendering The Fat

That doesn’t cut it

A single question is the determining factor for the approach of a ItemRenderer.

Q: Does the content require something other than

text or a label function can provide?A) No, formatting, custom styling, truncated textB) Yes, I need some icons or checkbox

Page 25: Rendering The Fat

Just some formatting…

• Extend the Base ItemRenderer Class for the component– AdvancedDataGridItemRenderer– DataGridItemRenderer– Etc.

• They extend UITextField• Override validateProperties();

Page 26: Rendering The Fat

ValidateProperties()• The part of DataGridItemRender that:– Sets the Text property on the TextField– Sets the Tooltip– Applies WordWrap based on Column

settings

• Apply any necessary formatting based on the data here

Page 27: Rendering The Fat

Unhealthy Text Renderer

<mx:AdvancedDataGridColumn headerText=“Add User"><mx:itemRenderer>

<mx:Component><mx:HBox width="100%" height="100%">

<mx:Label id=“userLabel” text="{data.name}“ styleName="{((data.name ==

'Jack') ? 0x990000 : 0x000000)}”/><mx:Image source=“{data.imageURL}” />

</mx:HBox></mx:Component>

</mx:itemRenderer></mx:AdvancedDataGridColumn>

Page 28: Rendering The Fat

What is wrong with it?• Improper use of a Container• Unknown length of the user name• ScrollBars• Inline ItemRenders are unable to be

reused elsewhere in the application

Page 29: Rendering The Fat

Healthy Text Rendererpublic class ExpiredUserItemRenderer extends AdvancedDataGridItemRenderer{

override public function validateProperties():void{

super.validateProperties();if (data && listData){

text = listData.label;if((data is Person) && (data as Person).isExpired == true){

setStyle("color", "0x990000");toolTip = “Warning! “ + listData.label;

}else {

setStyle("color", "0x000000");toolTip = listData.label;

}}

}}

Page 30: Rendering The Fat

Why Is It Healthy?• It is still just a TextField• Does the least amount of work to

present the custom text• No additional overhead from

Container classes or UIComponent

Page 31: Rendering The Fat

Rendering Other Controls

• When rendering images or multiple controls:– Extend UIComponent– Implement Interfaces• IDataRenderer• IListItemRenderer• IDropInListItemRenderer (Optional)

– Build Custom Functionality

Page 32: Rendering The Fat

Interfaces Part 1• IDataRenderer– data (value:Object)

• Provides the data object for the entire row

Page 33: Rendering The Fat

Interfaces Part 2• IListItemRenderer– All renderers must implement this

interface– Does not define any new methods– Extends several other Flex Interfaces– UIComponent already has required

properties and methods

Page 34: Rendering The Fat

Interfaces Part 3• IDropInListItemRenderer (Optional)– listData (value:BaseListData)

• Provides additional information to the renderer: Column Index, Row Index, dataField

• Allows the renderer to be re-used with different data fields and List components

Page 35: Rendering The Fat

Custom Functionality• Since we are extending

UIComponent, we have the Flex Component Life Cycle

• createChildren()• commitProperties()• measure()• updateDipslayList(…)

Page 36: Rendering The Fat

Unhealthy Renderer<?xml version="1.0" encoding="utf-8"?><mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script><![CDATA[

protected function linkbutton_clickHandler(event:MouseEvent):void{

// navigate to data.url}

]]></mx:Script>

<mx:HBox><mx:Label id="city" text="City: {data.city}" /><mx:Label id="state" text="State: {data.state}“ />

</mx:HBox><mx:LinkButton label="More Information“ click="linkbutton_clickHandler(event)"/>

</mx:VBox>

Page 37: Rendering The Fat

Another Unhealthy Renderer

override protected function commitProperties():void {if(dataChanged) {

// start overremoveChild(pdfIcon);removeChild(labelField);

}}

override protected function updateDisplayList( … ):void {super.updateDisplayList(unscaledWidth, unscaledHeight);

if(data && !pdfIcon) {createPDFIcon();}

if(data && !labelField) {createLabelField();

}// position & sizing logic…

Page 38: Rendering The Fat

What is wrong with it?• Improper use of the display list

• Using removeChild() & addChild() every time the data changes when unnecessary

• If you know what you need, create it once and update it when the data changes

Page 39: Rendering The Fat

Healthy Versionoverride protected function commitProperties():void {

if(dataChanged) {// update the text on the labelif(data) {

labelField.text = data.labelField;labelField.visible = true;

} else {labelField.text = “”;labelField.visible = false; }

}}

Page 40: Rendering The Fat

Healthy Component Renderer

Example of a Text & Icon Renderer

Page 41: Rendering The Fat

Tips for Healthy ItemRenderers

1. Avoid extending or containing anything in the mx.containers.* package.

2. Using a Repeater3. Using Remote Objects! Don’t Do it!4. Inappropriate use of the display list.

• addChild(), removeChild(), etc.5. Excessive recursion in the UIComponent

lifecycle.6. Directly modifying the data model,

remember it’s a view

Page 42: Rendering The Fat

Guidelines

When displaying:• Text: Extend base ItemRenderer

component• Images & Controls: Extend UIComponent• Add items to the display list once.• Avoid removing items from the display list

unless necessary

Page 43: Rendering The Fat

Summary• Know the issues related to a poorly

performing DataGrid• Ask the right question before

creating a custom ItemRenderer• Base ItemRenderer classes,

UITextField and UIComponent are your friends

• Don’t be afraid to get in there

Page 44: Rendering The Fat

Questions?

Page 45: Rendering The Fat

Thank You

Ben Schmidtke IIIConsultant - Digital Primates IT Consulting Group

[email protected]

Page 46: Rendering The Fat

Bonus Slides

Page 47: Rendering The Fat

Performance Note

A majority of all performance issues with AdvancedDataGrid are related to improper use of a custom item renderer.

Even if when updating the dataProvider collection more than necessary, a single poorly made item renderer can decrease performance severely.

Page 48: Rendering The Fat

The DataProvider• Will accept pretty much anything override public function set dataProvider

(value:Object):void

Behind the scenes if it does not meet certain criteria, it becomes something else.

Page 49: Rendering The Fat

The DataProviderAll data is or becomes one of two types:

• ICollectionView– ArrayCollection– XMLListCollection

• IHierarchicalCollectionView– HierarchicalCollectionView

Page 50: Rendering The Fat

Behind The Scenes if (value is Array) { collection = new ArrayCollection(value as Array); } else if (value is XMLList) {

collection = new XMLListCollection(value as XMLList); }

...

else { // convert it to an array containing this one item var tmp:Array = []; if (value != null) tmp.push(value);

collection = new ArrayCollection(tmp); }

Page 51: Rendering The Fat

CollectionEventcollection.addEventListener(

CollectionEvent.COLLECTION_CHANGE, …);

AdvancedDataGrid watches for CollectionEvent to respond accordingly keeping things up to date.

HierarchicalCollectionView Caches parent/child relationships for quick lookups and respond to the parent & children properties changing.

Page 52: Rendering The Fat

Issue 1: CollectionEvent

• Every time a collection event is dispatched on the dataProvider, AdvancedDataGrid may perform a considerable amount of work including:

– Rebuilding the data view– Reconstructing Hierarchical Structures &

Updating Cached Collections if necessary– Setting the data on all visible renderers

Page 53: Rendering The Fat

DataProvider Guidelines

• Manage your data prior setting the dataProvider– ArrayCollection, XMLListCollection or

HierarchicalCollection

• Apply updates to data objects in bulk if possible– Example: When editing a property, set the

value once not one character at a time.