PDA

View Full Version : How best to handle this? (asynchronous issue)


Mortimer Jazz
10-07-2006, 02:29 PM
Hi, I'm doing the following in my App:

1. Loading in some XML (for a menu)
2. Displaying it using a Tree component
3. Automatically opening the Tree at a certain node (ie using 'expandItem()')

Problem:
When the xmlLoads I assign it to the Tree's dataProvider and then call Tree.expandItem(), but it looks like I must wait for a few milliseconds for the Tree to populate, else the call to expandItem() fails. I guess this is fair enough, but how best to deal with that?

Currently:
I am using a timer, but I'm sure this can't be best practise. Is there a built in mechanism for dealing with this type of scenario?

Code Example:
Here's an easy way to see what I'm talking about. The xml and mxml are here. Save the xml out in to its own file ("tutorialMenu.xml").
Look in the mxml's onMenuDataLoaded method and comment out one of the options.
You should find it only works when you use the timer to give an extra 10ms delay - this behaviour may possibly vary on other machines, depending on processor power etc.

//---- THE XML (tutorialMenu.xml) -----------------------|
<?xml version="1.0" encoding="utf-8"?>
<node title="Mail Box">
<node title="Inbox">
<node title="Marketing"/>
</node>
<node title="Outbox">
<node title="Professional"/>
<node title="Personal"/>
</node>
<node title="Sent"/>
</node>

//---- THE MXML --------------------------------
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="onLoad();"
>
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;

[Bindable]
private var _menuItems:XMLList;

private function onLoad():void{
trace("::APPLICATION LOADED::");
menuDataRequest.send();
}

//Called by HTTPService
private function onMenuDataLoaded(event:ResultEvent):void{
trace("::DATA LOADED::");
_menuItems = event.result.node;
menuTree.dataProvider = _menuItems;

//-----COMMENT ONE OF THE FOLLOWING OPTIONS OUT-----
//menuTree.expandItem(_menuItems[0], true); //THIS DOESN'T WORK HERE
timer();
}

//Called by Tree's onCreationComplete
private function initMenuTree():void{
trace("::TREE INITIALISED::");
}

public function timer():void {
var myTimer:Timer = new Timer(10, 1);
myTimer.addEventListener("timer", timerHandler);
myTimer.start();
}

public function timerHandler(event:TimerEvent):void {
menuTree.expandItem(_menuItems[0], true);
}

]]>
</mx:Script>
<mx:HTTPService id="menuDataRequest" url="tutorialMenu.xml" resultFormat="e4x"
showBusyCursor="true" useProxy="false" result="onMenuDataLoaded(event);"
/>

<mx:Panel id="menuPanel" width="30%" height="100%" title="nwebb tutorials">
<mx:Tree id="menuTree" width="100%" height="100%" showRoot="false" horizontalScrollPolicy="off"
labelField="@title"
creationComplete="initMenuTree();"
/>
</mx:Panel>
</mx:Application>



...I'm thinking maybe Try..catch..finally or something, but I don't know if there is a better way. I obviously need to catch any errors and deal with them gracefully, and I'm sure I shouldn't be relying on a Timer here!!

Mortimer Jazz
10-09-2006, 10:45 AM
Solution:

_menuItems = event.result.node;
menuTree.dataProvider = _menuItems;
menuTree.validateNow(); // <---------------call validateNow() :)
menuTree.expandItem(_menuItems[0], true);

ronok
10-23-2006, 12:18 AM
I'd like to set the tree's openItems back to how they were before the httpService was called.

I've tried everything I can think of, including this:
http://lordbron.wordpress.com/2006/07/28/flex-20-reopening-a-tree-after-updating-the-dataprovider/
But I cannot get it to work.

Here's some of the code I've been working with:

[Bindable]
public var openTreeItems:Object = new Object();
[Bindable]
public var refreshTree:Boolean = false;

private function saveItem():void{
openTreeItems = tree1.openItems;
refreshTree = true;
EditItem.send();
}

private function resultHandler(event:ResultEvent):void{
var result:XML = event.result as XML;
xmlData = result.output.item;
tree1.dataProvider = xmlData;
tree1.validateNow(); // <---------------call validateNow() :)
//tree1.expandItem(xmlData[0], true);
refreshTree = false;
tree1.openItems = openTreeItems;
}