Friday, May 23, 2008

All Flex developers should know this

I sort of thought I didn't have to worry about memory leaks in Flex, because garbage collection would come to my rescue and sweep away the cruft. However, after what I learned last night (links below), I am reminded of a friend's favorite interview question: is it possible to have memory leaks in Java?

My friend would ask this and the greener candidates would emphatically reply, "No!" He liked asking that question, because he knew there were ways to leak memory in Java despite all the hype about garbage collecting. Sure, in most cases you don't have to worry about cleaning up after yourself. But I guess the smarter folks (not me) just know that it all depends on what you're doing and how you do it.

I stumbled on this post from Dan Schultz, who gives some nice tips on when to use weak or strong references when you add an event listener in Flex. Dan references another article from David Colleta which provides a little more insight.

I am using a Timer in a project that I'm working on, and fortunately I learned this before I had to trouble shoot the associated problems of using the wrong type of reference in my code.

Thanks, guys!

Tuesday, May 13, 2008

Passing out the cigars...

My first Flex app is running in production. It's just another chart, but I learned a lot and it was fun!

Flex Revelation Number Nine

Being new to Flex, I'm having epiphanies and revelations on a daily basis. I love it, but I hope the frequency of these events will diminish.

Here's my latest epiphany. I probably should have just known this already. I blame it on my percieved notion that there just aren't any good books available yet for Flex 3, so stubbornly I wait and beat my head.

My Epiphany on What Happens when MXML is converted into ActionScript

I want to explain something I didn't initially understand about how MXML is converted into ActionScript. MXML tags represent ActionScript objects. So if I want to declare a LineChart object and set the values of it's width and height properties, I would do this in MXML:

<mx:LineChart id="myChart" width="200" height="200" />

That would make a very boring line chart. When this MXML is converted into ActionScript it would look something like this:

import mx.charts.LineChart;

private var myChart : LineChart = new LineChart();

myChart.width = 200;
myChart.height = 200;

But what if the LineChart object had a property that required another object, not just a simple text string or number? This is a silly question in the context of ActionScript, but how do you pass in an object like this when you're using MXML?

The last option is what didn't click for me right away. For example, to configure the background color of a chart, you set the fill property of the LineChart object. But the fill property needs to be an object that implements the IFill interface (a SolidColor or LinearGradient). To do this in purely MXML, you therefore have to do this:

<mx:LineChart id="myChart" width="200" height="200">

   <mx:fill>
        <mx:SolidColor color="0x000000" /> <!-- black -->
   </mx:fill>

</mx:LineChart>

What's happened here is subtle (well for newbies like me, atleast). Each tag always starts w/it's namespace (the "mx:"). What follows the "mx:" always seemed to be the name of a class. So <mx:LineChart> is a LineChart object. But look at the first child of the <mx:LineChart> tag, it's name is fill and there is no class named fill in the Flex API. The fact that it starts w/a lowercase letter is a big clue.

So here's my big epiphany: In MXML, a child tag is just a property of its parent.

Which means that the following are equivalent ways of setting properties of objects in MXML.

The normal way that didn't blow my mind:

<mx:LineChart width="200" />

Or this way, which sort-of-did-until-now:

<mx:LineChart>
   <mx:width>200</mx:width>
</mx:LineChart>

Doh!

Monday, May 12, 2008

Creating Line Charts in Flex 3

Related Posts:

Making a Line Chart in 5 steps

There are many ways to make your charts, what follows is a recipe that allows you to tweak common aspects of the chart. Steps 3 through 5 are not necessarily required.

1. Create the Application and LineChart tags

Start by creating a Flex application w/the Application tag.

Then use a <Script> block to write some ActionScript. Declare an ArrayCollection named myArrayCollection. In a real application this data could be retreived from the web server as XML.

Declare a LineChart named myChart in MXML. Then bind the myArrayCollection to the LineChart's dataProvider property, using the curly brace notation:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="vertical">

 <mx:Script>
     <![CDATA[

     import mx.collections.ArrayCollection;

     [Bindable] private var myArrayCollection : ArrayCollection =
         new ArrayCollection(
         [ { sales: 101000, month: new Date( '01/01/2008' ) },
         { sales: 350000, month: new Date( '02/01/2008' ) },
         { sales: 475000, month: new Date( '03/01/2008' ) },
         { sales: 425000, month: new Date( '04/01/2008' ) }
         ] );

     ]]>
 </mx:Script>

 <mx:LineChart id="myChart"
     dataProvider="{myArrayCollection}"
     width="400" height="400"
     showDataTips="true"
     >

 </mx:LineChart>
</mx:Application>

2. Configure the series property of the LineChart object

The series property defines the data we're plotting. For a LineChart, you need to define this as a LineSeries object. We're going to use the LineSeries to specify where the X and Y values are in the chart's dataProvider. So we specify field names from our canned data in the xField and yField properties.

If you want to plot multiple data series, tack on a LineSeries object for each series.

We want to override the default colors Flex uses to render the chart lines. To do this we set the lineStroke property to a Stroke object, this specifies the color and size of the painting "stroke".

Add the following, as a child tag to the LineChart element:

<mx:series>
 <mx:LineSeries displayName="Sales by Month"
     yField="sales" xField="month" >

     <mx:lineStroke>
         <mx:Stroke
             color="0x11538C"
             weight="3"
             alpha="1"
             />
     </mx:lineStroke>
        
 </mx:LineSeries>
</mx:series>

3. Configure the horizontalAxis and verticalAxis properties of the LineChart object

This is not mandatory, but I recommend it for better control over how your axis labels are displayed. You can specify four different types of axes:

  • LinearAxis - for numeric values
  • LogarithmicAxis - for numeric values
  • DateTimeAxis - for date values
  • CategoryAxis - the default, for your own categories

You can set various properties on these axis objects, we are using a DateTimeAxis and a LinearAxis in this chart. Add the following, as a child tag to the LineChart element:

<mx:horizontalAxis>
 <mx:DateTimeAxis id="hAxis"
     dataUnits="months"
     alignLabelsToUnits="true"
     displayLocalTime="true"/>
</mx:horizontalAxis>

<mx:verticalAxis>
 <mx:LinearAxis id="vAxis" />
</mx:verticalAxis>

4. Configure the horizontalAxisRenderer and verticalAxisRenderer properties of the LineChart object

Axis renderers control how each axis is displayed, and are optional in this approach. Note how we use data binding to specify which axis each renderer should apply to. And again, add the following, as a child tag to the LineChart element:

<mx:horizontalAxisRenderers>
 <mx:AxisRenderer axis="{hAxis}"
     showLine="true"
     tickPlacement="outside"
     />
</mx:horizontalAxisRenderers>

<mx:verticalAxisRenderers>
 <mx:AxisRenderer axis="{vAxis}"
     showLine="false"
     tickPlacement="none"
 />
</mx:verticalAxisRenderers>

5. Add a Legend to your chart

You can optionally add a legend. You do this with data binding, by setting the dataProvider property of a Legned object. Add the Legend object as a child to the Application (not the LineChart):

<mx:Legend dataProvider="{myChart}" />

Keep on tweakin'

Check out the Flex 3 API for details on all of the classes mentioned here. Here are some more properties of the LineChart object that you can tweak:

  • seriesFilter - use this to modify the filters for each line, you can set this to a blank array to remove drop shadows
  • backgroundElements - use this to configure grid lines
  • fills - use this property to specify the background color of the chart

If you've been following along, you should have produced the app below. Right click to view the final source.