View Full Version : How to return in this function?
Selecters75
01-29-2008, 05:53 PM
Hi guys, hope you can help me on this one.
I have a class to load an XML file. I’m trying this:
package {
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.events.*;
public class retornaXML{
private var _xml:XML;
public function retornaXML() {
cargarXML();
}
private function cargarXML():void {
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, xmlLoaded);
loader.load(new URLRequest("LocalData.xml"));
}
private function xmlLoaded(e:Event):void {
_xml = new XML(e.target.data);
trace(_xml);
//THE TRACE HERE WORKS PERFECT AND RETURNS THE XML
}
public function get elXML():XML {
return _xml;
//THIS RETURNS null
}
}
}
I want something like this:
var mivariable:retornaXML = new retornaXML();
trace(mivariable.elXML);
but this trace returns null, since the xml file (I think) is not loaded yet. What should I do?
Thanks in advance.
xwielder
01-29-2008, 06:04 PM
Try this class:
package retornaXML
{
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.events.*;
public class retornaXML
{
static var _xml:XML = new XML ();
public function retornaXML ()
{
cargarXML ();
}
private function cargarXML ():void
{
var loader:URLLoader = new URLLoader ();
loader.addEventListener (Event.COMPLETE, xmlLoaded);
loader.load (new URLRequest("LocalData.xml"));
}
private function xmlLoaded (event:Event):void
{
_xml = new XML(event.target.data);
trace (_xml);
}
public function get elXML ():XML
{
return (_xml);
}
}
}
Selecters75
01-29-2008, 06:51 PM
Thanks for your answer.
But, I only see the instance declaration for _xml different from my code. I tested anyways and works exactly like my code (returns null).
xwielder
01-29-2008, 06:55 PM
Questions:
1. Where/how on your timeline code do you call/create reference to retornaXML?
2. Where/how on your timeline code do you call/create reference to elXML?
Selecters75
01-29-2008, 07:05 PM
Questions:
1. Where/how on your timeline code do you call/create reference to retornaXML?
2. Where/how on your timeline code do you call/create reference to elXML?
I'm trying to reference retornaXML in frame 1, first (and only) scene of my movie. Next line, I try to trace the result, like this:
var mivariable:retornaXML = new retornaXML();
trace(mivariable.elXML); //this returns null
I know if I trace mivariable.elXML in the next scene it gives time to xml to load and displays ok, but I'trying to avoid scenes.
thanks again.
dr_zeus
01-29-2008, 08:44 PM
The problem is that your XML file hasn't loaded yet. You need to wait for it to finish before accessing elXML.
Dr_Zeus is right, you need to wait for the XML to load, to do that, you can dispatch an event, like so;
In .fla
var myloadXml:loadXml = new loadXml("images.xml");
myloadXml.addEventListener("xmlParsed", callbackHandler);
*/
package {
import flash.events.*;
import flash.net.URLRequest;
import flash.net.URLLoader;
public class loadXml extends EventDispatcher {
public var myXML:XML;
private var myXLoader:URLLoader;
private var myXMLURL:URLRequest;
private var XML_URL:String;
public function loadXml(url:String) {
myXML = new XML();
XML_URL = url;
myXMLURL = new URLRequest(XML_URL);
myXLoader = new URLLoader(myXMLURL);
myXLoader.addEventListener(Event.COMPLETE, completeHandler);
myXLoader.addEventListener(IOErrorEvent.IO_ERROR, handleError);
}
private function completeHandler(e:Event):void {
myXML = XML(e.target.data);
dispatchEvent(new Event("xmlParsed"));
}
private function handleError(event:IOErrorEvent):void {
trace("Error loading XML");
}
}
}
Selecters75
01-29-2008, 11:28 PM
Thank you guys for your answers.
I think I could use add another event like ProgressEvent.PROGRESS to check if the file is loaded or not, right?. But how?
Thanks!
sgartner
01-30-2008, 12:08 AM
Thank you guys for your answers.
I think I could use add another event like ProgressEvent.PROGRESS to check if the file is loaded or not, right?. But how?
Thanks!
If you're just looking to delay the animation for a moment until an XML file is loaded you could just do something like this:
if (mivariable == undefined) // This will only be true once.
{
var mivariable:retornaXML = new retornaXML();
}
if (!mivariable.elXML)
{
trace(mivariable.elXML);
// XML is loaded, move on
gotoAndPlay("SomeCoolFrame");
}
// ToDo: Check some timer and do something if xml loading takes too long.
// Play this same frame again.
gotoAndPlay("loadingXML");
If the XML file is large, then this is probably too simple, but you did say that the file was loaded if you checked in the next frame.
Why would you need to use progress when the COMPLETE event tells you when the XML has loaded? Progress tells you how much as loaded, across the entire load operation.. It seems redundant to set up a if/else or similar clause to check the progress event, when you could just use COMPLETE.
Selecters75
01-30-2008, 04:02 AM
Why would you need to use progress when the COMPLETE event tells you when the XML has loaded? Progress tells you how much as loaded, across the entire load operation.. It seems redundant to set up a if/else or similar clause to check the progress event, when you could just use COMPLETE.
I'm already using the COMPLETE event. And it works. But please take a look at my code again:
package {
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.events.*;
public class retornaXML{
private var _xml:XML;
public function retornaXML() {
cargarXML();
}
private function cargarXML():void {
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, xmlLoaded);
loader.load(new URLRequest("LocalData.xml"));
}
private function xmlLoaded(e:Event):void {
_xml = new XML(e.target.data);
trace(_xml);
//THE TRACE HERE WORKS PERFECT AND RETURNS THE XML (EVENT COMPLETE).
}
public function get elXML():XML {
return _xml;
//THIS RETURNS null
}
}
}
I'm trying to instance this class, and then returns the xml as a class property. Like this:
var mivariable:retornaXML = new retornaXML();
trace(mivariable.elXML); // RETURNS null, XML IS NOT LOADED YET.
Thats because I started to try other options, check progress, etc.
Selecters75
01-30-2008, 04:05 AM
If you're just looking to delay the animation for a moment until an XML file is loaded you could just do something like this:
if (mivariable == undefined) // This will only be true once.
{
var mivariable:retornaXML = new retornaXML();
}
if (!mivariable.elXML)
{
trace(mivariable.elXML);
// XML is loaded, move on
gotoAndPlay("SomeCoolFrame");
}
// ToDo: Check some timer and do something if xml loading takes too long.
// Play this same frame again.
gotoAndPlay("loadingXML");
If the XML file is large, then this is probably too simple, but you did say that the file was loaded if you checked in the next frame.
Thanks, your solution could work. But, what happen if I load other movies, start others, whatever, in THE SAME frame? If I play the frame again I play the whole frame.
Selecters75
01-30-2008, 04:14 AM
Right now, I'm trying something like this:
package {
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.events.*;
public class retornaXML{
private var _xml:XML;
private var xmlloaded:Boolean = false; // ---------THIS VAR ONLY WORKS LIKE A FLAG
public function retornaXML() {
cargarXML();
}
private function cargarXML():void {
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, xmlLoaded);
loader.load(new URLRequest("LocalData.xml"));
}
private function xmlLoaded(e:Event):void {
_xml = new XML(e.target.data);
trace(_xml);
xmlloaded = true; // VAR IS TRUE NOW
//THE TRACE HERE WORKS PERFECT AND RETURNS THE XML (EVENT COMPLETE).
}
public function get elXML():XML {
if (xmlloaded) {
return _xml;
} else {
trace("FLAG IS FALSE");
return ;//WHAT CAN I USE AT THIS POINT TO CALL THIS METHOD AGAIN TO CHECK IF xmlloaded IS TRUE? (IF XML IS LOADED)
}
}
}
}
Thanks in advance!
sgartner
01-30-2008, 05:22 AM
Right now, I'm trying something like this:
package {
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.events.*;
public class retornaXML{
private var _xml:XML;
private var xmlloaded:Boolean = false; // ---------THIS VAR ONLY WORKS LIKE A FLAG
public function retornaXML() {
cargarXML();
}
private function cargarXML():void {
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, xmlLoaded);
loader.load(new URLRequest("LocalData.xml"));
}
private function xmlLoaded(e:Event):void {
_xml = new XML(e.target.data);
trace(_xml);
xmlloaded = true; // VAR IS TRUE NOW
//THE TRACE HERE WORKS PERFECT AND RETURNS THE XML (EVENT COMPLETE).
}
public function get elXML():XML {
if (xmlloaded) {
return _xml;
} else {
trace("FLAG IS FALSE");
return ;//WHAT CAN I USE AT THIS POINT TO CALL THIS METHOD AGAIN TO CHECK IF xmlloaded IS TRUE? (IF XML IS LOADED)
}
}
}
}
Thanks in advance!
Selecters,
Your user interface is only active when flash is allowed to finish the current frame. If you start programming with inner loops waiting for asynchronous actions to finish, like loading XML files, then your UI will completely stop updating. That's why I suggested looping the current frame until the XML file finishes loading. It's an extremely simplistic method.
With ActionScript 3.0 you really should be using events to drive your code. The concept that you can load an XML file from the server and in the next line access the XML is very rarely a reasonable expectation, no matter how small the XML file is, because of network delays.
Maybe the problem here is that you are trying to build a class around what is essentially not an object-oriented concept. This is a process that you are describing and you are trying to build an object around it and it's just not matching.
Please take a look at this instead:
// We won't leave this frame until the XML is loaded and
// laPersona is initialized, or until we catch an error and
// go to an error page.
stop();
var laPersona:Persona;
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, xmlLoaded);
// Error listeners
loader.addEventListener(IOErrorEvent.IO_ERROR, xmlDownloadError);
loader.addEventListener(SecurityErrorEvent.SECURIT Y_ERROR, xmlDownloadError);
loader.load(new URLRequest("LocalData.xml"));
function xmlLoaded (e:Event) : void
{
try
{
laPersona = new Persona(XML(e.target.data));
gotoAndPlay("display person"); // o algo
}
catch (error:Error)
{
trace("Error parsing XML: " + error);
// persona will still be null
gotoAndPlay("persona Load Failed");
}
}
function xmlDownloadError (event:Event) : void
{
trace("Error downloading XML: " + event);
gotoAndPlay("persona Load Failed");
}
This code is in persona.as
public class Persona
{
private var _xml:XML;
public function persona (personaXML:XML)
{
_xml = personaXML;
// ToDo: Do whatever processing is required to initialize persona
}
public get nombre ()
{
return(_xml.persona.nombre);
}
public get anos ()
{
// Calculate age by getting the birthdate from the persona XML
// and comparing it to the current date.
return(_xml.persona.cumpleaño - hoy); // This is pseudocode
}
// ToDo: Write other methods and properties for persona here
}
I started writing the code with Spanish variables and comments, etc. but in the end I got lazy. The assumption here is that the XML represents one "person" and so the class represents that person (not the process of downloading XML).
The current frame will continue to display (with any sub-animations on it running) until one of two things happens: Either the XML will finish downloading and fire the "COMPLETE" event, or an error occurs. There is another error scenario that I'm not covering here, and that is that downloading the XML takes too long, so some sort of timeout event should probably be included here as well.
Any code that is intended to require the loaded XML (using laPersona) will be in the "display person" named frame. If you're not familiar with the concept of naming frames, think of this line as gotoAndPlay(2) which would continue processing at frame 2.
If this isn't clear, please ask questions about it.
Selecters75
01-30-2008, 05:34 AM
THANK YOU VERY MUCH sgartner and all of you that answered my question.
sgartner: EXCELLENT approach and BETTER explanation. Now I see the point. Hope you guys have a nice day.
|
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.