Skip to content
September 20, 2010 / jetspiceflex

Cool Flex Skin

I use flexLib alot.  A recent port used .png art assets for the buttons and such.  The original target platform was the iPad.  Upscaling all the graphics for netbooks and desktops would have been time-consuming, and made the app bigger than necessary.  Enter: Enhanced Button Skin.  Here’s an example of it’s use:

Advertisements
September 16, 2010 / jetspiceflex

HTML and XML Garbage Collection in Adobe AIR

Let’s say you want to build an RSS reader in AIR, and you need full HTML support to display the feed. Your reader might switch between a few feeds so you are also loading the XML dynamically.

You’ll notice two things:

  • As the app runs, your memory usage keeps growing and growing.
  • Some RSS entries are too big to be displayed entirely.

This is because:

  • XML is not being garbage collected.
  • The HTML component’s height can only be 2880. (or 4096 in AIR2)

A solution for the HTML height limitation challenge is to dynamically populate a container with multiple HTML components using actionScript (like, in a VBox).

The XML that I was using had a tag which contained HTML. I was fortunate enough to be able to parse the HTML-inside-the-XML and divide it into several chunks by using “<br/>” as a delimiter:

private function createHTML():void
{
	//rss is the XML from the feed
	//currentItem is the current entry within the feed being displayed
	var content:String = String(rss.item[currentItem].content);
	//by putting the delimiter in parenthesis ( ), it is appended to the array
	var array:Array = content.split(/()/);
	var html:HTML;

	for (var i:uint; i < array.length; i ++)
	{
		html = new HTML();
		html.width = this.width;
		html.htmlText = array[i];
		this.addChild(html);
	}
}

When you change the XML feed or change currentItem, you’ll need to remove the the HTML components (firstly setting their content to null), and also the XML feed. Thanks to Greg Wilson’s Ramblings on garbage collection.

private function clearHTML():void
{
	var html:HTML;
	for (var i:uint; i < this.numChildren; i++)
	{
		if (this.getChildAt(i) is HTML)
		{
			html = HTML(this.getChildAt(i));
			html.htmlText = ""; //set the content to null
		}
	}
	this.removeAllChildren();
}

Before loading any other xml feeds, do this first:

System.disposeXML(rss);

I don’t advise passing the XML down to nested components, because of the way AIR prepares XML for garbage collection (as in, it doesn’t).
Instead, convert what you need to a string or array or arrayCollection, and pass that down to nested components. I do this right away and System.disposeXML(rss) immediately afterwards. For this same reason, I would avoid binding for a project like this. MXML and binding are super fast ways to develop, but in this case, the garbage collection is a bigger issue.

After all that, if the app’s memory usage still grows, you can follow Sean Christmann’s advice (from Craftymind)  here.