Volledige versie bekijken : XML laden via class
xanuex
%Europe/Berlin %398 %2009, 09:33
Ik ben bezig om mijn XML uit te lezen via een class. Ik heb hierbij de volgende code:
package
{
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
public class XmlLoader
{
private var loader:URLLoader = new URLLoader();
private var path:String = "";
private var request:URLRequest;
private var XMLData:XML;
// *************************************************
// XmlLoader Constructor
// *************************************************
public function XmlLoader(object:Object):void {
setPath(object.path);
request = new URLRequest(path);
loader.addEventListener(Event.COMPLETE, onXMLLoad);
loader.load(request);
}
// *************************************************
// Events
// *************************************************
public function onXMLLoad(event:Event):void {XMLData = new XML(URLLoader(event.target).data);}
// *************************************************
// Get Functions
// *************************************************
public function getLoader():URLLoader {return loader;}
public function getPath():String {return path;}
public function getRequest():URLRequest {return request;}
public function getXMLData():XML {return XMLData;}
// *************************************************
// Set Functions
// *************************************************
public function setPath(value:String):void {path=value;}
}
}
Main stage
import XmlLoader;
var xmlData:XmlLoader = new XmlLoader({path:"xml/xmlData.xml"});
trace(xmlData.getXMLData());
Helaas krijg ik er alleen null uit. Als ik een trace in de functie onXMLLoad zet krijg ik wel resultaat.
Iemand die ziet wat ik niet zie?
Alvast bedankt.
Marcel
Bartj3
%Europe/Berlin %412 %2009, 09:54
op het moment dat je traced is de xml nog niet daadwerkelijk geladen,
wat je kan doen is een event dispatchen in je onxmlload functie, daar naar luisteren in je main, en de trace pas doen als hij het event binnenkrijgt
daandebanaan2
%Europe/Berlin %431 %2009, 10:21
package
{
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.EventDispatcher;
public class XmlLoader
{
private var loader:URLLoader = new URLLoader();
private var path:String = "";
private var request:URLRequest;
private var XMLData:XML;
// *************************************************
// XmlLoader Constructor
// *************************************************
public function XmlLoader(object:Object):void {
setPath(object.path);
request = new URLRequest(path);
loader.addEventListener(Event.COMPLETE, onXMLLoad);
loader.load(request);
}
// *************************************************
// Events
// *************************************************
public function onXMLLoad(event:Event):void {
XMLData = new XML(URLLoader(event.target).data);
dispatchEvent(Event.COMPLETE);
}
// *************************************************
// Get Functions
// *************************************************
public function getLoader():URLLoader {return loader;}
public function getPath():String {return path;}
public function getRequest():URLRequest {return request;}
public function getXMLData():XML {return XMLData;}
// *************************************************
// Set Functions
// *************************************************
public function setPath(value:String):void {path=value;}
}
}
en op je main
import XmlLoader;
var xmlData:XmlLoader = new XmlLoader({path:"xml/xmlData.xml"});
xmlData.addEventListener(Event.COMPLETE, function(e:Event){
trace(xmlData.getXMLData());
});
Ik heb het niet getest, maar het zou moeten werken
xanuex
%Europe/Berlin %466 %2009, 11:11
Ik was nog aan het uitzoeken hoe ik EventDispatch moest gebruiken, vrij onbekend voor mij. Bij deze bedankt voor je voorbeeld.
Als ik het goed begrijp is EventDispatch een soort van doorgeefluik die in dit geval in de functie onXMLLoad de event status doorgeeft. Deze wordt door de EventListener op de mainstage opgepakt waarna de trace uitgevoerd wordt?
Ik krijg de melding "Call to possibly undefined method dispatchEvent" na uitvoeren.
jaspermuts
%Europe/Berlin %492 %2009, 11:48
je moet even EventDispatcher (of een subclass ervan) extenden om dispatchEvent te kunnen gebruiken.
Ik zie dispatchEvent altijd als 'schreeuw nu dat er iets is gebeurd!', omdat iedereen die er naar luistert ( de event listeners ) het dan 'hoort'.
Je kunt elk Event 'roepen'.. je kunt ook best een IOErrorEvent dispatchen in de completehandler als je wilt. Maar dat is niet zo handig ;)
xanuex
%Europe/Berlin %510 %2009, 12:15
Inmiddels had ik de class XMLLoader al uitgebreid met die van de dispatchEvent
public class XmlLoader extends EventDispatcher
Dit geeft me de volgende melding:
1067: Implicit coercion of a value of type String to an unelated type flash.events:Event.
Als ik de melding goed lees lijkt het erop dat Event.COMPLETE een waarde bevat die niet tot het type Events hoort?
dispatchEvent(Event.COMPLETE);
Ter info, ik heb de code op de mainstage gewijzigd in
import XmlLoader;
var xmlData:XmlLoader = new XmlLoader({path:"xml/xmlData.xml"});
xmlData.addEventListener(Event.COMPLETE, TraceMe);
function TraceMe(e:Event) {
trace(xmlData.getXMLData());
};
Zelfde effect, andere schrijfwijze.
Even terugkomend op dispatchEvent, ik kan niet goed terugvinden wat deze nu doorgeeft. Je geeft aan dat deze 'schreeuwt als er iets gebeurd', zegt het "hallo" of maakt het alleen geluid :) Geeft het dus een waarde door of alleen een seintje (true/false?)?
Dauntless
%Europe/Berlin %526 %2009, 12:38
Event.complete is een String die simpelweg aanduid wat voor event het is. Als je een event van dat type wil dispatchen moet je een nieuw event aanmaken (new Event()) en daar dan die string aan meegeven:
dispatchEvent(new Event(Event.COMPLETE));
xanuex
%Europe/Berlin %554 %2009, 13:18
Bedankt, dit is in ieder geval een oplossing voor het probleem :)
Ga nog even verder kijken naar dispatch en zijn functies.
daandebanaan2
%Europe/Berlin %572 %2009, 13:44
Sorry, ik had het even snel gemaakt... domme fouten, sorry.
jaspermuts
%Europe/Berlin %654 %2009, 15:42
Even terugkomend op dispatchEvent, ik kan niet goed terugvinden wat deze nu doorgeeft. Je geeft aan dat deze 'schreeuwt als er iets gebeurt', zegt het "hallo" of maakt het alleen geluid :) Geeft het dus een waarde door of alleen een seintje (true/false?)?
Het 'schreeuwt' de instantie van het event zelf. Afhankelijk van het soort (de class) event kun je in de handler meer gegevens ophalen. Het type (event.type) en de bron (event.currentTarget) zijn altijd terug te vinden. Je kunt ook custom events maken door de Event class te extenden, en ze bijvoorbeeld een property 'sourceURL' te geven, als je dat nodig zou hebben in de handler.
Om nog even terug te komen op waarom Event.COMLETE geen event is: het type van een Event is gewoon een String, je bent ook niet verplicht die constantes te gebruiken, je kunt ze ook zelf verzinnen:
private function onXMLLoad(e:Event):void
{
this.dispatchEvent(new Event('zomaariets'));
}
// ergens anders
xmlloader.addEventListener('zomaariets', onZomaarIets);
function onZomaarIets(e:Event):void
{
trace(e.type); // geeft: zomaariets
}
sidar
%Europe/Berlin %821 %2009, 19:43
Dit is hoe ik mijn xml inlaad
package sidar.loaders
{
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
/**
* Loads an XML and uses a callback function to parse the data.
* @author Sidar Talei
*/
public class XMLLoader
{
private var mCallBack:Function;
public function XMLLoader(url:String callBack:Function) : void
{
mCallBack = callBack;
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, xmlLoaded);
loader.load(new URLRequest(url));
}
private function xmlLoaded(e:Event) : void
{
(e.target as URLLoader).removeEventListener(Event.COMPLETE, xmlLoaded);
var xml:XML = new XML((e.target as URLLoader).data);
mCallBack.call(this, xml);
}
}
}
en dan
private var mXmlLoader:XMLLoader = new XMLLoader ("data.xml", onXML);
private function onXML(xml:XML) : void
{
//init xml data hier
}
daandebanaan2
%Europe/Berlin %428 %2009, 10:17
Wat een frapante manier om dit te doen, zo krijg je namelijk een erg vreemde gelaagdheid in je classes. Classen die elkaar niet hoeven te kennen gaan ineens functies van elkaar aanroepen, dat is niet nodig.
zoals we eerder lieten zien kan je beter een event dispatchen in het child (Jou XMLLoader Class) en de parent (classe die XMLLoader aanroept) laten "luisteren" naar het event van XMLLoader.
Zo hoeft XMLLoader niks te weten van de classe die hem aanroept, al is het slechts een functie.
sidar
%Europe/Berlin %044 %2009, 01:03
Zit bijna geen verschil in, alleen moet je bij de class die dispatched nog de data achterhalen.
Ik geef die direct mee. Je moet zowiezo refereren naar een functie dus zie totaal niet waarom dit een ramp zou zijn. Zoveel code is het niet, nadat de xml is verwerkt kan je het direct op null zetten.
zoals we eerder lieten zien kan je beter een event dispatchen in het child (Jou XMLLoader Class) en de parent (classe die XMLLoader aanroept) laten "luisteren" naar het event van XMLLoader.
Veel mensen gaan niet goed om met events, en halen die niet weg nadat ze verwerkt zijn. Bij het dispatchen van je xml, moet je zowiezo een instance maken waarbij je een listener toevoegt en een bijhorende functie. Basically the same thing.
Mijn xml class is zo minimaal dat het niet zoveel uitmaakt of het nou wel of niet van andere classes af weet. Veel doet het niet, het geeft alleen data weg.
"Beter" heeft te maken met de design van je structuur. Im keepin my way =P.
daandebanaan2
%Europe/Berlin %434 %2009, 10:26
true. Beter is een verkeerde verwoording. Het is wel frappant, een functie meegeven is meer een javascript manier van programmeren, en met een full-blown oop is het niet gebruikelijk zo'n design pattern aan te houden.
Maar je hebt gelijk, Basically the same thing.
jaspermuts
%Europe/Berlin %658 %2009, 15:47
Hè... ik snap de beargumentatie niet.
Eens ben ik het dat het niet gebruikelijk is, maar bij je redenen raak ik je kwijt.
Wat geef je nou normaal gesproken als 2e argument mee als je addEventListener() gebruikt? ook een functie toch?
urlloader.addEventListener(Event.COMPLETE, onComplete);
private function onComplete(event:Event):void
{
trace(XML(event.target.data));
}
// of
new XmlLoader('data.xml', onXML)
private function onXML(xml:XML):void
{
trace(xml);
}
Ik vind het maar een klein verschil.. Of zou je het logischer vinden als er een functie addLoader() oid was?
sidar
%Europe/Berlin %726 %2009, 17:25
Als ik hem goed begrijp, is het netter om Classes zo min mogelijk van elkaar te laten weten.
Ik stop een functie in mijn XMLloader die behoord tot mijn Class die de XMLloader aanmaakt.
Ik denk dat hij daarop doelt. Dat je classes zo min mogelijk afhankelijk van elkaar maakt.
(correct me if im wrong though xD)
Maarja ik heb altijd het idee dat classes met elkaar bemoeien aangezien je toch de properties veranderd.
Ik ben al een lange tijd bezig met flash, maar optimizen en goeie designs uitvogelen is niet zo een makkelijk proces.
jaspermuts
%Europe/Berlin %965 %2009, 23:09
Ik begreep ook wel zoiets inderdaad, dat het ging om de afhankelijkheid, maar aangezien de functie variabel is, is de afhankelijk niet groter dan bij een event listener.. En bij een event listener moet je toch nog weten naar wélk event je moet luisteren, dat lijkt me ook afhankelijkheid.
vBulletin® v3.8.1, Copyright ©2000-2012, Jelsoft Enterprises Ltd.