Ultrashock Forums > Flash > ActionScript
AS3 - Control code execution flow - loading XML and returning to document class

You are currently viewing our website as a guest which gives you limited access to forums, files and other resources.

Click here to join now for free, and start interacting with our members, download files and much more!

Click here if you are looking for our Flash files and other professional assets.
 
Post Reply | View first unread | Rate Thread Search this Thread | Thread Tools | Display Modes

#1
Bookmark and Share!
AS3 - Control code execution flow - loading XML and returning to document class
Old 2010-02-09

Hi all

I have a document class (Main.as) which is getting way too big so I want to structure my code better.

I'm struggling to get my class "ApplicationDataLoader.as" to return a value to my document class (Main.as). As a result "Main.as" carrys on code execution before ApplicationDataLoader finishes loading the XML...

I want to load the XML (applicationData.xml) in a class called "ApplicationLoader.as" which is external to Main.as.

I then want to populate a globally accessible class called "ApplicationData.as" so that I can retrieve my application data at any time and from any class in my project.

I have the following classes:
  • Main.as
  • ApplicationDataLoader.as
  • ApplicationData.as

Main.as currently looks like this:
Code:
package
{
	import flash.display.MovieClip;
	
	public class Main extends MovieClip{
		
		public static const APPLICATION_DATA_PROVIDER_PATH:String = "xml/applicationData.xml";
		
		public function Main() {
			ApplicationDataLoader.loadApplicationDataXml(APPLICATION_DATA_PROVIDER_PATH);
			

			trace("In Main() method");
			
			//When the ApplicationDataLoader has finished loading I want to continue code below but code execution continues anyway before ApplicationDataLoader has had chance to finish loading the xml

			//Once I get this working nicely I will then load another XML document using the skinID obtained from the load of applicationData.xml
			
		}
	}
}
ApplicationData.as looks like this
Code:
package 
{
	public class ApplicationData 
	{
		private var _skinID:String;
		
		public function ApplicationData():void {
						
		}
		
		//getters and setters
		public function get skinID():String { return _skinID; }
		
		public function set skinID(value:String):void 
		{
			_skinID = value;
		}
	
	}
}
ApplicationDataLoader.as currently looks like this:
Code:
package 
{
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.events.Event;
	
	public class ApplicationDataLoader 
	{
		public static var _appDataLoader:URLLoader;		
		public static var _appDataXml:XML;
		public static var _appData:ApplicationData;
		
		
		public function ApplicationDataLoader():void {
			trace("In ApplicationDataLoader()");
		}
		
		public static function loadApplicationDataXml(path:String):void {
			trace("In loadApplicationDataXml()");
			_appDataLoader = new URLLoader();
			_appDataLoader.addEventListener(Event.COMPLETE, onCompleteApplicationDataLoad);
			_appDataLoader.load(new URLRequest(path));
		}
		
		public static function onCompleteApplicationDataLoad(evt:Event):void{
			trace("In onCompleteApplicationDataLoad()");
			_appDataLoader.removeEventListener(Event.COMPLETE, onCompleteApplicationDataLoad);
			
			_appDataXml = new XML(evt.target.data);
			setData(_appDataXml);
		}
		
		public static function setData(_appDataXml:XML):void {
			trace("In setData()");
			_appData = new ApplicationData();
			_appData.skinID = _appDataXml.attribute("skinID");
			
			trace("skinID=" + _appData.skinID);
		}
	}
	
}
ApplicationData.xml looks like this:
Code:
<?xml version="1.0" encoding="UTF-8" ?> 
<application skinID="1"></application>
This should be simple I'm sure. Perhaps I'm incorrectly using static references or maybe my whole approach is incorrect. Can anybody help?

Thanks in advance :-)
postbit arrow 7 comments | 213 views postbit arrow Reply: with Quote   
Registered User
JimTester is offline
seperator
Posts: 82
2005-03-06
JimTester lives in United Kingdom
JimTester's Avatar
seperator

Ultrashock Member Comments:
JimTester's Avatar JimTester JimTester is offline JimTester lives in United Kingdom 4 Weeks Ago #2 Old  
Perhaps I should re-phrase... I'm doing something stupid (or not doing something which is obvious to others).

I want to create an asset loader class (ApplicationDataLoader) that gets called by Main.as (my document class).

When Main.as 'tells' ApplicationDataLoader to load the external XML files I want code execution to halt untill ApplicationDataLoader has finished doing its job of loading the XML.

I think my approach is wrong.

Can anybody spare 5 mins to look at my code and point me in the right direction?

Thanks

Jim :-)
Reply With Quote  
Isocase's Avatar Isocase Isocase is offline Isocase lives in United States 4 Weeks Ago #3 Old  
Why don't you just dispatch an event when your ApplicationDataLoader has finished loading? Your ApplicationDataLoader can listen for that event and run the rest of your code then.
Reply With Quote  
JimTester's Avatar JimTester JimTester is offline JimTester lives in United Kingdom 4 Weeks Ago #4 Old  
Thanks for your reply Isocase :-)

You might not believe this but I've never dispatched an event before.
I've got a really patchy knowledge of AS3. I can get stuff to work most of the time but I'm never really 100% confident that the methods I use conform to best practices.

I'll have a read about dispatching events. Do I need to be thinking along the lines of custom events as well?
Reply With Quote  
Isocase's Avatar Isocase Isocase is offline Isocase lives in United States 4 Weeks Ago #5 Old  
You can just dispatch the Event.COMPLETE event that your _appLoader listens for. If you wanted to pass a parameter in your event, then you would need to create a custom event.

One thing to keep in mind is since your class is a static class you will need to create a EventDispatcher variable and have that dispatch the event.
Reply With Quote  
JimTester's Avatar JimTester JimTester is offline JimTester lives in United Kingdom 2 Weeks Ago #6 Old  
Last edited by JimTester : 2 Weeks Ago at 05:39.
Isocase. Thanks very much for your advice :-)

A couple of questions...

QUESTION 1:
If I create an EventDispatcher variable to dispatch the event then how do I use addEventListener on the static class in order to handle the event? It seems that I can't do this in AS3.

i.e. if I do the following in a static class:
var ed:EventDispatcher = new EventDispatcher();
ed.dispatchEvent(new Event(READY));

and i try the following in my document class:
MyStaticClass.addEventListener(READY, onReadyDoSomething);

then I get the error:
"1061: Call to a possibly undefined method addEventListener through a reference with static type Class."



QUESTION 2.
As an alternative approach I tried the following...
...Is this correct?

Main.as
Code:
package
{
	import flash.display.MovieClip;
	import flash.events.Event;
	
	public class Main extends MovieClip{
		
		private static const APPLICATION_DATA_PROVIDER_PATH:String = "xml/applicationData.xml";
		private static var _appData:ApplicationData; 
		private var _adl:ApplicationDataLoader;
		
		
		public function Main() {
			_adl = new ApplicationDataLoader(APPLICATION_DATA_PROVIDER_PATH);  
			_adl.addEventListener(ApplicationDataLoader.APP_DATA_READY, onApplicationDataReady);
		}
		
		private function onApplicationDataReady(evt:Event):void {
			//Populate our static ApplicationData object in order to make 
			_appData = _adl.appData;
			//The above line of code makes our application data (_appData) available from any other class by calling Main.appDataValues());
			
			trace("At this point we can carry on doing whatever we need to do!");
		}
		
		
		//This public static method is here so that I can get access to the private static _appData variable
		//I can do this from any other class by calling Main.appDataValues();
		public static function get appDataValues():ApplicationData {
			return _appData;
		}
	}
}
ApplicationDataLoader.as
Code:
package 
{
	import flash.events.EventDispatcher;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.events.Event;
	
	public class ApplicationDataLoader extends EventDispatcher
	{
		private var _appDataLoader:URLLoader;		
		private var _appDataXml:XML;
		public var appData:ApplicationData;
		
		public static const APP_DATA_READY:String = "application_data_ready_for _use";
		
		public function ApplicationDataLoader(path:String):void {
			loadApplicationDataXml(path);
		}
		
		private function loadApplicationDataXml(path:String):void {
			_appDataLoader = new URLLoader();
			_appDataLoader.addEventListener(Event.COMPLETE, onCompleteApplicationDataLoad);
			_appDataLoader.load(new URLRequest(path));
		}
		
		private function onCompleteApplicationDataLoad(evt:Event):void{
			_appDataLoader.removeEventListener(Event.COMPLETE, onCompleteApplicationDataLoad);
			
			_appDataXml = new XML(evt.target.data);
			setData(_appDataXml);
		}
		
		private function setData(_appDataXml:XML):void {
			appData = new ApplicationData();
			appData.skinID = _appDataXml.attribute("skinID");
			
			dispatchEvent(new Event(APP_DATA_READY));
		}
	}
	
}
Reply With Quote  
Isocase's Avatar Isocase Isocase is offline Isocase lives in United States 2 Weeks Ago #7 Old  
For static classes you have to actually create the static methods addEventListener and removeEventListener. Below is a quick example of what I mean. If you don't create those methods then you will get an error if you try to add and EventListener to your static class.

Code:
package {
	
	public class MyStatic {
		
		private static var _eventdispatcher:EventDispatcher = new EventDispatcher();
		
		public function MyStatic() {
		}
		
		public static function addEventListener(type:String, eventHandler:Function):void {
			_eventdispatcher.addEventListener(type, eventHandler);
		}
		
		public static function removeEventListener(type:String, eventHandler:Function):void {
			_eventdispatcher.addEventListener(type, eventHandler);
		}
	}
}
Reply With Quote  
JimTester's Avatar JimTester JimTester is offline JimTester lives in United Kingdom 2 Weeks Ago #8 Old  
The breakthrough
Thanks again Isocase. That all makes good sense.

I now have 2 different methods of loading external XML.
I have attached a zip file of a small cut down FlashDevelop project which illustrates the 2 methods.

If you're reading this and don't use FlashDevelop don't panic - just take a look at the .as files. The FLA contains nothing of importance other than the class path.

Method 1 involves loading an XML file consisting of application data. I use a static ApplicationData variable in the document class (Main.as) and dispatch an event in ApplicationDataLoader which Main.as handles. It then continues the code execution flow.

Method 2 uses a static class and the static addEventListener & removeEventListener methods as specified by Isocase in his previous post.


I'm dead chuffed with this - Thanks Isocase.

If anyone has any views on which is the best method out of the 2 (in terms of the one-off loading of external files) then I'd be really interested.

Jim :-)
Attached Files
File Type: zip loadingExternalAssets.zip (25.3 KB, 1 views)
Reply With Quote  
Thread Tools
Display Modes Rate This Thread
Rate This Thread: