Rendering The Fat
Upcoming SlideShare
Loading in...5
×
 

Rendering The Fat

on

  • 5,197 views

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

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

Statistics

Views

Total Views
5,197
Slideshare-icon Views on SlideShare
4,671
Embed Views
526

Actions

Likes
1
Downloads
23
Comments
0

4 Embeds 526

http://www.digitalprimates.net 476
http://www.slideshare.net 34
http://blogs.digitalprimates.net 15
http://www.lmodules.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Rendering The Fat Rendering The Fat Presentation Transcript

    • Rendering the Fat:
      How to Keep Your DataGrid Healthy
      Ben Schmidtke III
      Digital Primates
      bschmidtke@digitalprimates.net
      Twitter: stunnedgrowth
    • Who Am I
      Ben Schmidtke III
      Consultant - Digital Primates IT Consulting Group
      Flash Platform Developer for 11 years
      Adobe Certified Instructor
      Twitter: stunnedgrowth
    • Agenda
      Overview of List Components
      DataGrid and AdvancedDataGrid
      Why should we take care of them
      ItemRenderers
      Building Slim ItemRenderers
      Tips and Guidelines
      Questions
    • 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
    • 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.
    • Out Of The Box
      Flex 3 provides several components for presenting data in a list format:
      List Controls
      List
      Tree
      DataGrid
      TileList
      Menu
      And More…
      • Data Visualization
      AdvancedDataGrid
      OLAPDataGrid
    • General Features
      Support Multiple Data Types
      Drag and Drop
      Scrolling - Vertical and Horizontal
      Cell Editing
      Variable Row Height
      labelFunction
      And more...
    • 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
    • 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
    • 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
    • Why should we take care of it?
      Performance
      Troubleshooting
      Flexibility
      Maintainability
    • It Takes Work
      Large quantities of information
      Each cell is a component
      The more rows and columns displayed decreases performance
    • 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.
    • It All Boils Down To
      Unexpected Results
      Poor User Experience
      Cranky Client 
      Your Personal Health: Stress
    • 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.)
    • 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
    • The Default: It’s Text!
      DataGrid
      DataGridItemRenderer
      Extends UITextField > FlexTextField > TextField
      AdvancedDataGrid
      AdvancedDataGridItemRenderer
      Extends UITextField > FlexTextField > TextFIeld
    • Why Is It Text?
      Extremely lightweight
      Direct and to the point
      Take the least amount of time to create and display
      No container overhead
    • 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.
    • Too Much Functionality
      Containers are performance heavy
      Everything that makes them easy, slows them down
      10 Rows + 10 Columns = 100 Containers
    • Custom ItemRenderers
      Depending 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.
    • 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
    • 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>
    • 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 text
      B) Yes, I need some icons or checkbox
    • Just some formatting…
      Extend the Base ItemRenderer Class for the component
      AdvancedDataGridItemRenderer
      DataGridItemRenderer
      Etc.
      They extend UITextField
      Override validateProperties();
    • 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
    • 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>
    • 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
    • Healthy Text Renderer
      public 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;
      }
      }
      }
      }
    • 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
    • Rendering Other Controls
      When rendering images or multiple controls:
      Extend UIComponent
      Implement Interfaces
      IDataRenderer
      IListItemRenderer
      IDropInListItemRenderer (Optional)
      Build Custom Functionality
    • Interfaces Part 1
      IDataRenderer
      data (value:Object)
      Provides the data object for the entire row
    • 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
    • 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
    • Custom Functionality
      Since we are extending UIComponent, we have the Flex Component Life Cycle
      createChildren()
      commitProperties()
      measure()
      updateDipslayList(…)
    • 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>
    • Another Unhealthy Renderer
      override protected function commitProperties():void {
      if(dataChanged) {
      // start over
      removeChild(pdfIcon);
      removeChild(labelField);
      }
      }
      override protected function updateDisplayList( … ):void {
      super.updateDisplayList(unscaledWidth, unscaledHeight);
      if(data && !pdfIcon) {
      createPDFIcon();
      }
      if(data && !labelField) {
      createLabelField();
      }
      // position & sizing logic

    • 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
    • Healthy Version
      override protected function commitProperties():void {
      if(dataChanged) {
      // update the text on the label
      if(data) {
      labelField.text = data.labelField;
      labelField.visible = true;
      } else {
      labelField.text = “”;
      labelField.visible = false; }
      }
      }
    • Healthy Component Renderer
      Example of a Text & Icon Renderer
    • Tips for Healthy ItemRenderers
      Avoid extending or containing anything in the mx.containers.* package.
      Using a Repeater
      Using Remote Objects! Don’t Do it!
      Inappropriate use of the display list.
      • addChild(), removeChild(), etc.
      Excessive recursion in the UIComponent lifecycle.
      Directly modifying the data model, remember it’s a view
    • 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
    • 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
    • Questions?
    • Thank You
      Ben Schmidtke III
      Consultant - Digital Primates IT Consulting Group
      bschmidtke@digitalprimates.net
    • Bonus Slides
    • 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.
    • 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.
    • The DataProvider
      All data is or becomes one of two types:
      ICollectionView
      ArrayCollection
      XMLListCollection
      IHierarchicalCollectionView
      HierarchicalCollectionView
    • 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);
      }
    • CollectionEvent
      collection.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.
    • 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
    • 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.