Passing the rest parameter

November 5, 2009 roustalski Leave a comment

As you probably know, you can create a function where the last parameter is a “…rest” variable.

You probably also know that when inside the function, the comma delimited variables from the caller show up as an array. This is unfortunate when you want to pass the set of values through to another function.

Enter the apply function. What this means is that you can take the array that just came in and pass the parameters off to another function in the same manner it came in, as long as it isn’t a constructor. Adobe has deferred that until later.

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/halo"
			   minWidth="1024" minHeight="768"
			   creationComplete="application1_creationCompleteHandler(event)">

	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
			import mx.utils.ObjectUtil;

			protected function application1_creationCompleteHandler(event:FlexEvent):void
			{
				one("this", "is", "a", "set", "of", "parameters");
			}

			private function one(...parameters):void
			{
				//Bummer, I can't send parameters down to two as it came in...
				two(parameters);

				//Or can I ?
				two.apply(this, parameters);

				//You can of course manipulate the rest parameter before passing it on...
				parameters.unshift(parameters.shift(), "really");

				two.apply(this, parameters);
			}

			private function two(...parameters):void
			{
				trace( ObjectUtil.toString(parameters) );
			}

		]]>
	</fx:Script>
</s:Application>

Application global access

October 14, 2009 roustalski Leave a comment

In flex 4, accessing your application globally has changed from Application.application in flex 3, to FlexGlobals.topLevelApplication.

Flex 3:

import mx.core.Application;
var myApp:MyApp = Application.application as MyApp;

Flex 4:

import mx.core.FlexGlobals;
var myApp:MyApp = FlexGlobals.topLevelApplication as MyApp;
Categories: Flex 4 Examples

s|global && mx|global embedded fonts

October 13, 2009 roustalski Leave a comment

I’m not sure how it happened, but yesterday we noticed our fonts were suddenly (magically) messed up. In one of our applications we reference a library source path containing a common css file and some fonts. In it we were embedding the fonts appropriately and had global style declarations so the embedded fonts would be applied to both sets of controls.

As an example:

/* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/halo";

@font-face {
	src: url("Arial.ttf");
	font-weight: normal;
	font-style: normal;
	fontFamily: "embededArialSpark";
}

@font-face {
	src: url("Arial.ttf");
	font-weight: normal;
	font-style: normal;
	fontFamily: "embededArialHalo";
	embedAsCFF: false;
}

mx|global
{
/*  This worked and appeared NOT to affect spark controls  */
/*	fontFamily: embededArialHalo;  */
/*	font-family: "embededArialHalo";*/
	font-family: embededArialHalo;
}
s|global
{
/*	Worked, but appeared to apply to MX controls as well, that is, you don't see the mx fonts  */
/*	fontFamily: embededArialSpark;  */
/*	font-family: "embededArialSpark";*/
	font-family: embededArialSpark;
}

However, in another base library we had another css file with the same fonts using almost the same declarations. It just so happened that we remade those sets of components and replaced that section of the library. We noticed that we had the same embedded fonts and decided to remove them since we had a newer common css in an assets library, but when we removed it our fonts were messed up. We tried editing our common css to do what was previously in the other library and still had no affect on the fonts.

So I created a sample app demonstrating the problem. You can download the source here.

As a workaround, use the global selector for sparks, and mx|ComboBox and other typed selectors for the halo components that you are using.

Categories: Flex Gotchas Tags: , , , , ,

<s:ItemRenderer/> currentState == null

October 1, 2009 roustalski Leave a comment

I received an Item renderer from my designer with a few states that were to be driven by some data. We are using an advanced data grid and one of the columns is rendered by this component.

We noticed that the state wasn’t reflected by the data despite the correct state being set. As it turns out, the ItemRenderer class has a getCurrentRendererState() method that can potentially return null – Specifically when there is no interaction (hovered, selected, etc…) and there is no “normal” state on your renderer.

So despite my setting the correct state, this base method was hijacking me and setting the state to null. You can fix this problem by overriding the method, or by overriding “setCurrentState” and not calling super.setCurrentState if the stateName is null.

Flex 4 Text Performance Issues

September 24, 2009 roustalski Leave a comment

We have been running into performance issues with a new MMSP level application where we render anywhere from 1 to thousands of items. We narrowed it down to the List, DataGroup, ItemRenderer, and related items and decided to run some tests to see what about them was taking so long.

We created an app that creates 5 lists, each with their own data group and item renderer files. We created one with vectors/gradients only (NoLabelNoBind), vectors/gradients with labels and no binding, vectors/gradients with labels and binding, and then two more with richtext in stead of labels.

We rendered 100, 200, 300, 400, and then 500 items, all of which finished except the 500 item test, where it got a 15 second script timeout exception thrown. Maybe our tests are bogus and we are doing something wrong, but we are ignorant of those techniques if that is the case. The bottom line from this test app is to use labels where RichText isn’t needed and don’t use binding but in stead set the properties of the labels from the Dto/Vo objects as the renderer receives the new item.

Per the adobe help docs, we tried adding the “useVirtualLayout” property to the layout property on the datagroup and list with the same results.

Speed Test

Speed Test

The associated source can be found here.

PUNQ 1.0 released

September 15, 2009 roustalski Leave a comment

I’ve been working on a free IT Search tool for the past couple of months at my company called PUNQ.

See the official press release here, a summary on the tool here, and the you-tube help videos here.

I think the toughest part of the project was integrating the code base among platform specific features including a web (flex) version and an air version for desktop apps.

Categories: Uncategorized

So you have memory problems in your Flex application?

September 3, 2009 roustalski Leave a comment

First, if you aren’t already acquainted with the memory issues in the flash player, browse through some of these links:

Grant Skinner:

Sean Christmann: http://www.craftymind.com/2008/04/09/kick-starting-the-garbage-collector-in-actionscript-3-with-air/

Alex Harui:

Adobe official docs: http://livedocs.adobe.com/flex/3/html/help.html?content=profiler_6.html

I would like to add a technique to the collective knowledge that I have implemented in our MVC framework and propagated through our legacy code base: IDisposable.

The contract of IDisposable is very simple, exposing a lone method: dispose(). An implementation of the interface has the following responsibilities:

  1. Follow the rules of the aforementioned links (e.g. removing event listeners)
  2. Call dispose on any IDisposable children that he is responsible for.
  3. Explicitly set all class level non-simple types to null, including splicing arrays, and deleting dictionary/object keys.

The reason for number 3 is very simple. Take a look at the following diagram taken from the garbage collection overview by Grant:

Credit to Grant Skinner: http://www.gskinner.com/blog/

Credit to Grant Skinner: http://www.gskinner.com/blog/

Since the first pass of the flash garbage collector is based off of reference counting, the goal is to remove all references that you can control in order to optimize for the collector. Let’s see an example.

private var _string1:String = "Don't bother disposing of me";
private var _a:Array;
private var _o1:Object;
private var _o2:Object;
private var _o3:Object;

function ohSnap():void
{
    _o1 = {label: "sweet"};
    _o2 = {label: "awesome", sweet: _o1};
    _o3 = {label: "cool", awesome: _o2, sweet: _o1};
    _a = [_o1, _o2, _o3];
}

Even if this array and collection of objects ends up white in the mark and sweep diagram above, they remain in memory until the second phase of the collector is activated. Why?

Lets count the references of the objects created in ohSnap:
o1: 4 references, by the array, o2, o3, and _o1.
o2: 3 references, by the array, o3, and _o2.
o3: 2 references, by the array and _o3.
a: 1 reference by _a

Now, let’s go on ahead and optimize our destruction by cleaning up these references in our dispose method:

public function dispose():void
{
    for ( var i:int = _a.length-1; i > -1; i-- )
    {
        var o:Object = _a[i];
        for ( var key:String in o )
        {
            delete o[key];
        }
        _a.splice(i, 1);
    }
    _o1 = null;
    _o2 = null;
    _o3 = null;
    _a = null;
}

Deleting the keys of the objects removes the references of o1 in o2 and o3, and o2 in o3, while splicing the array removed the references to o1, o2, and o3. Finally, the class level references to the objects were removed, leaving a reference count of zero for the three objects and array.

In addition to having the marksweep collection method run less because the reference count method removes the objects first, implementing a standard contract in your applications for all objects makes memory management, such as identifying leaks easier because the cleanup of each object is in a standardized place.

SystemManager.application == null using SWFLoader or Loader

September 2, 2009 roustalski 3 comments

So you need access to the application property inside the system manager you just loaded using SWFLoader or Loader huh?

There are two options:

1. Listen for the FlexEvent.APPLICATION_COMPLETE event on the System manager after the loader fires the Event.INIT event.

However, that sucks if you need access to the application before it has finished its construction.

While it isn’t ideal for my situation (I wanted access to the application before the initialize event was fired), I was able to get hold of the application after the initialize event had been fired, but before the creation complete event had been fired.

2. Listen for the Event.ENTER_FRAME event on the system manager, and check if the application property is not null. Tada. Crappy I know, but what can you do?

Also, remove the event listener once you have access to the application (unless you want it?).

Casting swfLoader.content as SystemManager

September 2, 2009 roustalski Leave a comment

So I was trying to load an application into another and was using SwfLoader.

When I received the INIT (or COMPLETE) events from the loader, I was trying to cast the .content property as SystemManager (since that’s what it is) but the type cast was failing.

The solution is to set the SwfLoaders loader context property with a new context and pass in the current application domain.

var loader:SwfLoader = new SWFLoader();

loader.loaderContext = new LoaderContext(false, new ApplicationDomain(ApplicationDomain.currentDoman));

Now you can cast the content property as a SystemManager.

Yippie.

Categories: Flex Gotchas

IList’s itemUpdated method

August 28, 2009 roustalski Leave a comment

For those of you using an MVC framework like PureMVC, here is an example of updating a data item from a model. Once the view has the collection, there aren’t any new notifications or events unless an item is added or removed. Updates to existing items can occur by reference in the model. The example simulates data updates every 5 seconds and changes the email address of the two alternate items.

Application.mxml:

<?xml version=”1.0″ encoding=”utf-8″?>

<s:Application xmlns:fx=”http://ns.adobe.com/mxml/2009″

xmlns:s=”library://ns.adobe.com/flex/spark”

xmlns:mx=”library://ns.adobe.com/flex/halo” initialize=”windowedapplication1_initializeHandler(event)”>

<fx:Script>

<![CDATA[

import model.DataModel;

import mx.events.FlexEvent;

private var _dataModel:DataModel;

protected function windowedapplication1_initializeHandler(event:FlexEvent):void

{

_dataModel = new DataModel();

lst.dataProvider = _dataModel.dataCollection;

}

]]>

</fx:Script>

<s:List x=”120″ y=”66″font-size: 11pt; font-family: Monaco; color: rgb(153, 0, 0);”>lst” labelField=”email” width=”402″ height=”276″></s:List>

</s:Application>

DataModel:

package model

{

import flash.events.TimerEvent;

import flash.utils.Timer;

import mx.collections.ArrayCollection;

[Bindable]

public class DataModel

{

private var _dataCollection:ArrayCollection;

private var _updateTimer:Timer;

public function DataModel()

{

_dataCollection = new ArrayCollection();

var dd:DataDto = new DataDto();

dd.email = “russ.watson@abc.com”;

dd.name = “Russ Watson”;

_dataCollection.addItem(dd);

dd = new DataDto();

dd.email = “khayes@abc.com”;

dd.name = “Keith Hayes”;

_dataCollection.addItem(dd);

_updateTimer = new Timer(5000);

_updateTimer.addEventListener(TimerEvent.TIMER, onUpdateTimer);

_updateTimer.start();

}

public function get dataCollection():ArrayCollection

{

return _dataCollection;

}

public function set dataCollection(value:ArrayCollection):void

{

_dataCollection = value;

}

private function onUpdateTimer(e:TimerEvent):void

{

var mod:int = _updateTimer.currentCount % 5;

var dd:DataDto;

var oldVal:String;

var newVal:String;

switch ( mod )

{

case 0:

dd = dataCollection[0] as DataDto;

newVal = “russWatson@abc.com”;

break;

case 1:

dd = dataCollection[1] as DataDto;

newVal = “asdbadsfg@abc.com”;

break;

case 2:

dd = dataCollection[0] as DataDto;

newVal = “1234123@abc.com”;

break;

case 3:

dd = dataCollection[1] as DataDto;

newVal = “dfbsdfsdfh@abc.com”;

break;

case 4:

dd = dataCollection[0] as DataDto;

newVal = “34t6werh@abc.com”;

break;

case 5:

dd = dataCollection[1] as DataDto;

newVal = “mnbvcx@abc.com”;

break;

}

oldVal = dd.email;

dd.email = newVal;

dataCollection.itemUpdated(dd, “email”, oldVal, newVal);

}

}

}

DataDto:

package model
{
public class DataDto
{
private var _email:String;
private var _name:String;

public function DataDto()
{
}

public function get email():String
{
return _email;
}
public function set email(value:String):void
{
_email = value;
}

public function get name():String
{
return _name;
}
public function set name(value:String):void
{
_name = value;
}
}
}

Categories: Flex 4 Examples