Oct 9, 2008

Asynchronous execution of functions

Many a times in flex, we are faced with situations where we need to set some data that currently available to us in a component which has not yet been created! e.g. Say I am dynamically adding a VBox to a tab navigator, and that VBox contains a Label as child, I have a value that I want to set to the text of that Label but since that Label has not been created yet, I just cannot set it. To make it more clear look at the code snippet:
function someMethod() {
// somewhere deep down:
var str : String = "some value";
var vBox : MyVBox = new MyVBox();
tabNavigaor.addChild(vBox);
// this vBox contains a Label, whose text I want to set to 'str'.
}

since vBox has just been added, it has not been fully created and added to display list and hence Label also is not created yet. Infact if we try to access label, we will get null!

So, what's the solution?
One solution is that I define an inline (anonymous function) and attach it as event handler for 'creationComplete'. And in that functon I set the 'str' to Label. something like:

function someMethod() {
// somewhere deep down:
var str : String = "some value";
var vBox : MyVBox = new MyVBox();
tabNavigaor.addChild(vBox);
// this vBox contains a Label, whose text I want to set to 'str'.
vBox.addEventListener('creationComplete' function(e : Event) : void {
e.target['myLabel'].text = str;
}
}

This will solve the problem. But I have always been a bit finicky about 'inlined' functions. I mean what if the value of 'str' changes before the creationComplete has been fired?

Java solves this problem (in case of anonymous inner classes) by forcing that variable to be final so that it cannot be changed, but I dont see such a thing happening for flex.

Therefore, to ensure that this does not happen, we can use the following solution:
1. Define a normal function which has the same code as the anonymous function.
2. Write a AsyncFunction class which 'queues' the exection of a function and its params for later.
3. The AsyncFunction listens for some trigger (in this case 'creationComplete' and then dequeues the queued method and its params and executes them.

Following is the code for AsyncFunction :

package modules.model {
import flash.utils.Dictionary;
import mx.core.UIComponent;
import mx.utils.UIDUtil;
import flash.events.Event;

public class AsyncFunction {

private static const dict : Dictionary = new Dictionary();

public static function callLater(method : Function, triggerEventName : String, 
triggerComponent : UIComponent, ... args) : void {
triggerComponent.addEventListener(triggerEventName,asyncHandler);
var uid : String = UIDUtil.createUID();
triggerComponent.setStyle("___$uid",uid);
dict[uid] = {f : method, params : args};
}

private static function asyncHandler(triggerEvent : Event) : void {
var uid : String = triggerEvent.target.getStyle('___$uid');
if(dict.hasOwnProperty(uid)) {
var method : Function = dict[uid].f as Function;
method.apply(triggerEvent.target,dict[uid].params); 
// rollback:
triggerEvent.target.removeEventListener(triggerEvent.type,asyncHandler);
triggerEvent.target.setStyle('___$uid',null);
delete dict[uid];
}
}

}
}

Then, in our current situation just do this:
function someMethod() {
// somewhere deep down:
var str : String = "some value";
var vBox : MyVBox = new MyVBox();
tabNavigaor.addChild(vBox);
// this vBox contains a Label, whose text I want to set to 'str'.
AsyncFunction.callLater(setUpLabel, 'creationComplete', vBox, vBox, str);
}

private function setUpLabel(vBox : MyVBox, str : String) : void {
vBox['myLabel'].text = str;
}

That's it! Just one line of code : AsyncFunction.callLater(setUpLabel, 'creationComplete', vBox, vBox, str);
and you are guaranteed that your code will execute fine.

Oct 3, 2008

Deferred Instantiation

In order to optimize startup time, certain navigation containers such as Accordian, ViewStack and TabNavigator used what is called deferred creation. For Navigator containers, this means that only the container and its children, visible to the user are instantiated. The hidden containers are instantiated when focused upon.
To alter the order of instantiation Flex provides the creationPolicy property. This property is inherited by all subclasses of Container. The creationPolicy property can be altered in the following ways.

1. creationPolicy=”auto”
Flex does not create the children immediately, but instantiated them only when the user focuses on them. This deferred instantion raises the performance in that the navigatore container loads quickly. However, the user may experience a brief pause for the first time they navigate among containers.
If this attribute is set for a non-navigator component, then we must specify additional code to specify the order of creating the children.

2. creationPolicy=”all”
Flex instantiates all components. However, this may reduce the initial load time.

3. creationPolicy=”none”
Flex does not instantiate any of the components unless the programmer explicitly calls the instantiation methods (done through createComponents() method).

4. creationPolicy=”queued”
Flex instantiates the components one after the other. The order can be altered using the creationIndex property. If creationIndex is not assigned, the children are instantiated in the order they appear in the MXML.

However, deferred instantiation has its own set of disadvantages. Deferred instantiation is not usually preferred when using effects and transitions. It usually gets in the way of smooth transition performance because instantiation may occur in mid transaction. Of course, this may be only for the first time the transition is played.

Thanks,
Shaleen Jain

Oct 2, 2008

Forcing layout using validateNow()

Sometimes, (although rare) we may come across situations wherein we’d like flex to layout components at runtime immediately. As an example, you may have to increase the width of an image in a canvas at runtime and would immediately like to use this width for some processing. . If you let Flex do it, it might delay the processing of certain properties that may take long in computing. It might take sometime for the commitProperties() to be executed. To avoid this you may want to force the layout immediately.
             To do this, we use the validateNow() method of the component. According to LiveDocs,
validateNowValidates and updates the properties and layout of this object by immediately calling validateProperties(), validateSize(), and validateDisplayList(), if necessary.”
Also,
validateNow()-Validate and update the properties and layout of this object and redraw it, if necessary. Processing properties that require substantial computation are normally not processed until the script finishes executing. For example setting the width property is delayed, because it may require recalculating the widths of the objects children or its parent. Delaying the processing prevents it from being repeated multiple times if the script sets the width property more than once. This method lets you manually override this behavior
          However, since validateNow() forces validation in the same frame it may be processor intensive. So try and not use it unless it is absolutely necessary.

Thanks,
Shaleen Jain

Performance tuning using Flash Player Cache

A very good article on Improving performance of a Flex application using Flash Player cache can be found here.

What is mx_internal?

Here, I am going to tell you about the mx_internal namespace. You often come acrosss this work when you open any flex component.  I have used mx_internal namespace a couple of times, but I swear to god I have never understood what it means or why it is used. So I decided to plunge in a little bit and make some sense out of it.
So I decided to plunge in a little bit and make some sense out of it.

Before I get to that, it makes sense to discuss a little bit about namespaces. Namespaces are essentially used to limit the scope of methods, classes, variables or constants. One could say that they are used to avoid potential naming conflicts that may arise with other components having the same names. Namespaces are associated with a Uniform Resource Identifier that identifies the namespace. You can find more information on namespaces here.

Now, mx_internal is one such namespace that the Flex SDK uses to handle internal data. Just like all other namespaces, mx_internal contains a lot of variables which we can use in our code. To know which variables belong to mx_internal, dig into the Flex SDK code and you can find them. An example of the use of mx_internal can be found in the TextInput.as class of the Flex SDK. Some commonly used mx_internal variables/methods of this class are:

/**
* The internal subcontrol that draws the border and background.
*/
mx_internal var border:IFlexDisplayObject;

————————————————————————————–

mx_internal function get selectable():Boolean
{
return _selectable;
}

To you the mx_internal namespace, just import it and let Actionscript know you are using it.

import mx.core.mx_internal;

use namespace mx_internal;

You are then ready to use the variables of mx_internal.

Of course there are some issues with using this namespace. First there is no code hinting in Flex Builder when using this namespace. That means you have to dig yourself to know which variables are present in the namespace. Second, Adobe has mentioned this warning with using the namespace.

“This namespace is used for undocumented APIs — usually implementation details — which can’t be private because they need to visible to other classes. APIs in this namespace are completely unsupported and are likely to change in future versions of Flex.”

That means that the next time Flex updates happen and your code doesn’t work as it is supposed to, don’t blame Adobe.

Thanks,
Shaleen Jain