Laster inn data med kommandoer

Det er veldig vanlig å laste eksterne data (som SWF-filer) i løpet av kjøretid, men bare når dataene er fullstendig lastet, kan vi lese eller manipulere innholdet. Vanligvis må vi lytte til hele arrangementet som sendes av a loader eller URLLoader objekt som laster dataene for ferdigstillingshåndtering. Ofte skriver vi kode som laster dataene i en funksjon, og skriver kode som håndterer fullføringen av lastingen i en annen funksjon, men dette kan forbedres ved å gruppere hele lasteprosessen sammen ...

Denne opplæringen demonstrerer hvordan du lager en lastingsutvidelse til kommandorammen i min tidligere opplæring, Tenk i kommandoer del 1 av 2, for å pakke lastingen av ferdigstillingshåndteringen til ett sted. Denne lastetillegget kan også kombineres med scenestyringsrammen som er dekket i Thinking in Commands del 2 av 2. Mange klasser brukt i denne opplæringen er dekket i den forrige opplæringen, så jeg anbefaler at du leser de tidligere opplæringsprogrammene før du fortsetter.

I tillegg introduserer denne opplæringen begrepet dataadministrator, en sentral "bank" som lagrer referanser til dataobjekter. Du kan registrere data til datamaskinen med en unik nøkkelstreng, og senere få tilgang til dataene ved å gi den tilhørende nøkkelstrengen. Dette sparer deg for problemer med å holde referanser til dataobjekter og noen problemer med variabel omfang.

Forresten, trenger du GreenSock Tweening Platform for å fullføre disse eksemplene.


Hvorfor laste data med kommandoer?

Normalt håndterer vi de lastede dataene inne i den komplette hendelseslytterfunksjonen. Dette bryter fra to biter av kode som er logisk forbundet. Og ved å se på koden, kan tankestrømmen din bli avbrutt, da synet hopper fra lastingsfunksjonen til den komplette hendelseslytteren.

La oss se på logikkstrømmen av en naiv SWF-belastningstilgang.

Lasteren laster inn en SWF fra en URL, og onComplete () funksjonen påberopes av dispatchEvent () metode som sender en komplett hendelse, hvor dispatchEvent () Metoden er påkalt internt av lasteren. Vel, faktisk, er det påkalt av LoaderInfo objekt som tilhører loader objekt, men for enkelhet, la oss bare si det dispatchEvent () Metoden påberopes av Loader.

Deretter, innenfor onComplete () funksjon, den doMoreStuff () funksjonen påberopes etter at håndteringen av lasting er ferdig og, som funksjonens navn antyder, gjør flere ting.

Den høye logikkstrømmen er veldig lineær: påkalle Loader.load () metode først, onComplete () andre og doMoreStuff () tredje. Men som du vil legge merke til fra diagrammet, er hver funksjons invokasjon innebygd i funksjonskroppen til den forrige, noe som resulterer i en "nestet" kode. Etter min mening, hvis logikkstrømmen av en bestemt funksjonalitet er lineær, bør den tilhørende koden skrives på en lineær måte, ikke nestet. Ellers kan koden noen ganger bli forvirrende hvis innkallingsnestnivået er for høyt.

Dette er når Command-tilnærmingen kommer inn i spill. Fra diagrammet nedenfor kan vi se at koden er ganske lineær ved hjelp av kommandoer, idet alle kommandoene er lineært sammenkjedet av en seriell kommando. Selv om programmet "viderekobler" inn i setProperties (), addChildLoader (), og doMoreStuff () funksjoner; deres påkallelse er lineær.


Data Manager

Ok, før vi går ned til noe mer om lasting, la oss først ta en titt på DataManager klasse. En datastyrer lar deg knytte en nøkkelstreng med et dataobjekt, og du kan få en referanse til dette dataobjektet overalt i koden din. Med dataadministratoren trenger du ikke å bekymre deg for å holde data referanser og variabel rekkevidde. Alt du trenger å gjøre er å registrere et stykke data til lederen med en nøkkelstreng.

Kodingen er ganske enkel, som vist nedenfor:

 pakke data import flash.utils.Dictionary; offentlig klasse DataManager // en ordbok som opprettholder streng-data relasjoner privat statisk var _data: Dictionary = new Dictionary (); // returnerer dataobjektet knyttet til en nøkkelstreng offentlig statisk funksjon getData (nøkkel: streng): * return _data [key];  // registrerer et dataobjekt med en nøkkelstreng offentlig statisk funksjon registerData (nøkkel: String, data: *): void _data [key] = data;  // avregistrerer en nøkkelstreng offentlig statisk funksjon unregisterData (nøkkel: String): void delete _data [key];  // avregistrerer alle nøkkelstrenger offentlig statisk funksjon clearData (): void for (var-nøkkel: String i _data) delete _data [key]; 

Så når vi ønsker å registrere en nøkkelstreng "myData" med et dataobjekt - si en sprite - kan vi skrive koden som følger:

 var sprite: Sprite = new Sprite (); DataManager.registerData ("myData", sprite);

Senere, hvor som helst i koden, kunne vi skrive følgende kode for å få en referanse til sprite og legge den til en visningsliste. Det er så enkelt, ikke flere problemer med å opprettholde objektreferanser og variabel rekkevidde.

 var sprite: Sprite = DataManager. getData ("myData") som Sprite; container.addChild (sprite);

Naive Loading Approach

La oss nå se på hvordan den naive belastningsmetoden laster et eksternt bilde. Lastingskoden ligger i en funksjon, og ferdigstillingshåndteringskoden ligger i en annen. Vi skal legge inn tre bilder og legge dem til scenen når lastingen er fullført. Også, vi overvåker lastingsfremdriften ved å lytte til fremdriftshendelsene.


Trinn 1: Lag et Flash-dokument

Åpne Flash og opprett et nytt Flash-dokument.

Trinn 2: Lag en fremdriftslinje

Tegn en fremdriftslinje på scenen; Dette er for å representere lasting fremgang. Konverter hele fremdriftslinjen til et symbol og gi det et forekomstnavn på "progressBar_mc". Innenfor fremdriftslinjens symbol konverterer du den indre fremdriftslinjen til et annet symbol, og gir det et forekomstnavn på "innerBar_mc".


Trinn 3: Forbered bildene

Plasser tre bilder i samme mappe som FLA-filen, kalt "image1.jpg", "image2.jpg" og "image3.jpg". Slik ser de tre bildene ut.


Trinn 4: Opprett dokumentklassen

Opprett en ny AS-fil for dokumentklassen for FLA-filen. Koden er ganske enkel, og alle detaljer er forklart i kommentarene. Først blir tre lastere opprettet og lastingen begynner. På hver fremdriftshendelse oppdateres fremdriftslinjen. Når lastingen er fullført, farges fremdriftslinjen og de tre bildene fades i en-for-en.

 pakke import com.greensock.TweenMax; importer flash.display.DisplayObject; importer flash.display.Loader; importer flash.display.MovieClip; importere flash.events.Event; importer flash.events.ProgressEvent; importere flash.net.URLRequest; offentlig klasse NaiveLoading utvider MovieClip private var loader1: Loader; private var loader2: Loader; private var loader3: Loader; offentlig funksjon NaiveLoading () // krympe fremdriftslinjen til null skala fremdriftBar_mc.innerBar_mc.scaleX = 0; // lage lastere loader1 = ny Loader (); Loader2 = Ny Loader (); Loader3 = Ny Loader (); // legg til fremgangslyttere loader1.contentLoaderInfo.addEventListener (ProgressEvent.PROGRESS, onProgress); loader2.contentLoaderInfo.addEventListener (ProgressEvent.PROGRESS, onProgress); loader3.contentLoaderInfo.addEventListener (ProgressEvent.PROGRESS, onProgress); // legg til fullført lyttere loader1.contentLoaderInfo.addEventListener (Event.COMPLETE, onComplete); loader2.contentLoaderInfo.addEventListener (Event.COMPLETE, onComplete); loader3.contentLoaderInfo.addEventListener (Event.COMPLETE, onComplete); // start loading loader1.load (ny URLRequest ("image1.jpg")); loader2.load (ny URLRequest ("image2.jpg")); loader3.load (ny URLRequest ("image3.jpg"));  privat funksjon onProgress (e: ProgressEvent): void // beregne totalt biter for å laste var bytesTotal: uint = 0; bytesTotal + = loader1.contentLoaderInfo.bytesTotal; bytesTotal + = loader2.contentLoaderInfo.bytesTotal; bytesTotal + = loader3.contentLoaderInfo.bytesTotal; // beregne totalt biter lastet var bytesLadet: uint = 0; bytesLoaded + = loader1.contentLoaderInfo.bytesLoaded; bytesLoaded + = loader2.contentLoaderInfo.bytesLoaded; bytesLoaded + = loader3.contentLoaderInfo.bytesLoaded; // oppdatering fremdriftslinje skala fremdriftBar_mc.innerBar_mc.scaleX = bytesLoaded / bytesTotal;  privat var _completeCount: int = 0; privat funksjon onComplete (e: Event): void _completeCount ++; hvis (_completeCount < 3) return; //remove progress listeners loader1.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress); loader2.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress); loader3.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress); //remove completion listeners loader1.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete); loader2.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete); loader3.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete); var image1:DisplayObject = loader1.content; var image2:DisplayObject = loader2.content; var image3:DisplayObject = loader3.content; //adjust loaded image positions image1.x = 30, image1.y = 30; image2.x = 230, image2.y = 30; image3.x = 430, image3.y = 30; //add loaded images to display list addChild(image1); addChild(image2); addChild(image3); //fade out progress bar TweenMax.to(progressBar_mc, 0.5, autoAlpha:0, blurFilter:blurX:20, blurY:20); //fade in loaded images TweenMax.from(image1, 0.5, delay:0.5, alpha:0, blurFilter:blurX:20, blurY:20); TweenMax.from(image2, 0.5, delay:0.7, alpha:0, blurFilter:blurX:20, blurY:20); TweenMax.from(image3, 0.5, delay:0.9, alpha:0, blurFilter:blurX:20, blurY:20);   

Trinn 5: Test filmen

Trykk CTRL + ENTER for å teste filmen. Du får se at fremdriftslinjen forsvinner umiddelbart og de tre bildene falmer inn. Det er fordi bildene er lokale filer, noe som betyr at de kan lastes nesten umiddelbart. For å simulere nedlastingshastighet på Internett, velg først Vis> Last ned innstillinger> DSL som den simulerte nedlastingshastigheten, og trykk deretter CTRL + ENTER igjen uten å lukke testvinduet for å starte simulering av nedlastning på nettet. Denne gangen skal du se fremdriften vokse gradvis bredere før det fades ut.

Ok, det er på tide å laste bildene med kommandorammen.


Utility Commands

Før vi fortsetter, la oss lage noen verktøykommandoer som vil bli brukt senere i eksemplet. Igjen er disse kommandoklassene basert på kommandorammen som ble presentert i min tidligere opplæring (del 1), og jeg anbefaler at du går gjennom dem før du går videre. Hvis du har lest opplæringen før, kan du alltid gå tilbake hvis du trenger oppdatering av minnet.

Data Managers Commands

Her skal vi lage to kommandoer for registrering og avregistrering av data for dataleder klassen. De RegisterData kommandoen registrerer data til sjefen, mens UnregisterData kommandoen avregistrerer data.

 pakke kommandoer.data import kommandoer.kommando; importer data.DataManager; // Denne kommandoen registrerer data til datahåndboerens offentlige klasse RegisterData utvider kommandoen public var-nøkkel: String; offentlige vardata: *; offentlig funksjon RegisterData (nøkkel: String, data: *) this.key = key; this.data = data;  overstyr beskyttet funksjon utfør (): void DataManager.registerData (nøkkel, data); fullstendig(); 
 pakke kommandoer.data import kommandoer.kommando; importer data.DataManager; // denne kommandoen avregistrerer data fra datalederens offentlige klasse UnregisterData utvider kommandoen public var-nøkkel: String; offentlig funksjon UnregisterData (nøkkel: String) this.key = key;  overstyr beskyttet funksjon utfør (): void DataManager.unregisterData (nøkkel); fullstendig(); 

LoaderLoad-kommandoen

Denne kommandoen encapsulates a loader eksempel er laste() metode. Du kan gi en onProgress kommando som utføres på hvert fremdriftshendelse og en onComplete utført når lastingen er fullført. Legg merke til at fullstendig() Metoden påberopes når lastingen er fullført. Denne koden er ekstremt viktig. Hvis du ikke anvender metoden, vil kommandoen aldri bli ansett som fullført, og det kommer til å stramme hele applikasjonen i verste fall.

 pakke kommandoer.loading import kommandoer.kommando; importer flash.display.Loader; importere flash.events.Event; importer flash.events.ProgressEvent; importere flash.net.URLRequest; importer flash.system.LoaderContext; offentlig klasse LoaderLoad utvider kommando public var loader: Loader; offentlig var url: URLRequest; offentlig var kontekst: LoaderContext; Offentlig var påProgress: Kommando; offentlig var onComplete: Command; offentlig funksjon LoaderLoad (loader: Loader, url: URLRequest, kontekst: LoaderContext = null, onProgress: Command = null, onComplete: Command = null) this.loader = loader; this.url = url; this.context = context; this.onProgress = onProgress; this.onComplete = onComplete;  overstyr beskyttet funksjon utfør (): void // legg til lyttere loader.contentLoaderInfo.addEventListener (ProgressEvent.PROGRESS, progressListener); loader.contentLoaderInfo.addEventListener (Event.COMPLETE, completeListener); loader.contentLoaderInfo.addEventListener (Event.COMPLETE, loadingComplete); // start loading loader.load (url, kontekst);  privat funksjon loadingComplete (e: Event): void // fjern lytterne loader.contentLoaderInfo.removeEventListener (ProgressEvent.PROGRESS, progressListener); loader.contentLoaderInfo.removeEventListener (Event.COMPLETE, completeListener); loader.contentLoaderInfo.removeEventListener (Event.COMPLETE, loadingComplete); fullstendig();  Private Function ProgressListener (e: ProgressEvent): void // kjør onProgress kommandoen hvis (onProgress) onProgress.start ();  privat funksjon fullførtListener (e: Event): void // kjør kommandoen onComplete hvis (onComplete) onComplete.start (); 

InvokeFunction Command

Denne kommandoen encapsulates anropelsen av en annen funksjon. Den er laget for å gi deg mulighet til å angi en ekstra parametergruppe for funksjonen som skal påberopes.

 pakke kommandoer.utils import kommandoer.kommando; // denne kommandoen påkaller en funksjon offentlig klasse InvokeFunction utvider kommando public var func: Funksjon; offentlig var args: Array; offentlig funksjon InvokeFunction (func: Funksjon, args: Array = null) this.func = func; this.args = args;  overstyr beskyttet funksjon utfør (): void func.apply (null, args); fullstendig(); 

Det er det. Tid for eksemplet.


Trinn 1: Kopier Flash-dokumentfilen

Kopier FLA-filen fra forrige eksempel til en ny mappe og kopier bildefilene sammen med den.


Trinn 2: Opprett dokumentklassen

Opprett en ny AS-fil for dokumentklassen til den kopierte FLA-filen, kalt "LoadingDataWithCommands". Husk å endre dokumentets klassenavn i FLA-filen til denne nye.

Koden for dokumentklassen er ganske ren. Den setter bare den aktuelle scenen til en LoadingScene med en scene manager. Vi bruker scenarammen som ble presentert i min tidligere opplæring (del 2). Du kan sjekke det ut hvis du har glemt hvordan du bruker den.

 pakke import flash.display.MovieClip; importere scener.SceneManager; offentlig klasse LoadingDataWithCommands utvider MovieClip offentlig funksjon LoadingDataWithCommands () var sceneManager: SceneManager = new SceneManager (); sceneManager.setScene (nytt LoadingScene (dette)); 

Det er totalt to scener. De LoadingScene laster bildene og oppdaterer fremdriftslinjen. Etter at lastingen er fullført, går scenen til MainScene, som fades i de lastede bildene.


Trinn 3: Laster scenen

Utvid scene klasse for å opprette en ny klasse som heter LoadingScene. De container eiendom har en referanse til hovedsprite. Dette tillater oss å få tilgang til fremdriftslinjen senere.

 pakke import scenes.Scene; offentlig klasse LoadingScene utvider Scene private var container: LoadingDataWithCommands; offentlig funksjon LoadingScene (container: LoadingDataWithCommands) this.container = container; 

Nå lager intro-kommandoen for lastescenen. Introen vil skape tre lastere og starte lasteprosessen. Dette gjøres ved å overstyre createIntroCommand () metode. Følgende kode går inn i klassekroppen, samme som konstruktøren.

 // intro-kommandoen begynner lastingen av de tre bildene overstyrer offentlig funksjon createIntroCommand (): Command var loader1: Loader = new Loader (); var loader2: Loader = ny Loader (); var loader3: Loader = ny Loader (); var command: Command = new ParallelCommand (0, // krympe fremdriftslinjen til null skala nye SetProperties (container.progressBar_mc.innerBar_mc, scaleX: 0), // loading-relaterte kommandoer utført i serie nye SerialCommand (0, / / registrerer de tre lasteapparatene til datastyreren Ny ParallelCommand (0, Ny RegisterData ("Loader1", Loader1), Ny RegisterData ("Loader2", Loader2), Ny RegisterData ("Loader3", Loader3)), // Start 3 Lasting kommandoer parallelt nytt ParallelCommand (0, ny LoaderLoad (loader1, ny URLRequest ("image1.jpg"), null, ny InvokeFunction (onProgress) // onProgress kommando), ny LoaderLoad (loader2, ny URLRequest ("image2.jpg") , null, ny InvokeFunction (onProgress) // onProgress kommando), ny LoaderLoad (loader3, ny URLRequest ("image3.jpg"), null, ny InvokeFunction (onProgress) // onProgress kommando)))); returnere kommando; 

Deretter overstyre onSceneSet () metode. Denne metoden er påkalt når intro-kommandoen er fullført, og indikerer at lastingen er fullført. Innenfor denne metoden, forteller vi scenesjefen å flytte til hovedstedet. Før sceneovergangen utføres kommandoen outro først.

 overstyr offentlig funksjon onSceneSet (): void sceneManager.setScene (new MainScene (container)); 

Og deretter overstyre createOutroCommand. Denne kommandoen skal fade ut fremdriftslinjen.

 // kommandoen outro fjerner fremdriftslinjen overstyrer offentlig funksjon createOutroCommand (): Command var kommandoen: Kommando = ny SerialCommand (0, // fade ut fremdriftslinjen ny TweenMaxTo (container.progressBar_mc, 0.5, autoAlpha: 0, blurFilter : blurX: 20, uskarphet: 20), // fjern fremdriftslinjen fra visningslisten ny RemoveChild (container, container.progressBar_mc)); returnere kommando; 

Endelig, opprett onProgress metode som påberopes av InvokeFunction kommandoer.

 privat funksjon onProgress (): void // henter loader referanser fra data manager var loader1: Loader = DataManager.getData ("loader1") som Loader; var loader2: Loader = DataManager.getData ("loader2") som Loader; var loader3: Loader = DataManager.getData ("loader3") som Loader; // beregne totale biter for å laste var bytesTotal: uint = 0; bytesTotal + = loader1.contentLoaderInfo.bytesTotal; bytesTotal + = loader2.contentLoaderInfo.bytesTotal; bytesTotal + = loader3.contentLoaderInfo.bytesTotal; // beregne totalt biter lastet var bytesLadet: uint = 0; bytesLoaded + = loader1.contentLoaderInfo.bytesLoaded; bytesLoaded + = loader2.contentLoaderInfo.bytesLoaded; bytesLoaded + = loader3.contentLoaderInfo.bytesLoaded; // Oppdater fremdriftslinjen skala container.progressBar_mc.innerBar_mc.scaleX = bytesLoaded / bytesTotal; 

Trinn 4: Hovedscenen

Lag nå en ny klasse for hovedscenen, og utvide scene klasse.

 pakke import scenes.Scene; offentlig klasse MainScene utvider Scene private var container: LoadingDataWithCommands; offentlig funksjon MainScene (container: LoadingDataWithCommands) this.container = container; 

Overstyr createIntroCommand () metode. Denne metoden vil legge til leserne i visningslisten, og fade dem i en-for-en. I tillegg er datastøkkstrengene uregistrert fra datalederen.

 overstyr offentlig funksjon createIntroCommand (): Kommando // hente loader referanser fra data manager var loader1: Loader = DataManager.getData ("loader1") som Loader; var loader2: Loader = DataManager.getData ("loader2") som Loader; var loader3: Loader = DataManager.getData ("loader3") som Loader; var command: Command = new ParallelCommand (0, // lastet bildehåndtering kommandoer nye SerialCommand (0, // juster lastede bildeposisjoner nye ParallelCommand (0, nye SetProperties (loader1, x: 30, y: 30), nye SetProperties (loader2, x: 230, y: 30), nye SetProperties (loader3, x: 430, y: 30)), // legg til innlastede bilder til visningslisten ny ParallelCommand (0, nytt AddChild , loader1), ny AddChild (container, loader2), ny AddChild (container, loader3)), // fade i lastede bilder nytt ParallelCommand (0, ny TweenMaxFrom (loader1, 0.5, blurFilter: blurX: 20, uskarphet: 20 , nye TweenMaxTo (loader1, 0.5, autoAlpha: 1), ny TweenMaxFrom (loader2, 0.5, forsinkelse: 0.2, alfa: 0, blurFilter: blurX: 20, blurY: 20), ny TweenMaxTo (loader2, 0.5, delay: 0.2, autoAlpha: 1), ny TweenMaxFrom (loader3, 0.5, forsinkelse: 0.4, alfa: 0, blurFilter: blurX: 20, uskarphet: 20), ny TweenMaxTo , 0,5, forsinkelse: 0,4, autoAlpha: 1))), // unregsiter data fra dataleder ny ParallelCommand (0, ny UnregisterData ("loader1"), ny Unregi sterData ("loader2"), ny UnregisterData ("loader3"))); returnere kommando; 

Trinn 5: Test filmen

Ok. Vi er ferdige! Test filmen og simuler online nedlasting. Du vil se nøyaktig samme resultat som i forrige eksempel, men denne gangen er det alt gjort med kommandorammen og scenarammen.


Sammendrag

I denne veiledningen har jeg vist deg hvordan du laster inn eksterne bilder med kommandorammen. De LoaderLoad Kommandoen kan også brukes til å laste eksterne SWF-filer. Videre kan du lage dine egne kommandoer for å laste eksterne data annet enn bilder og SWF-filer, ved å inkapslere URLLoader klassen i kommandoene dine.

Vi har skrevet mer kode i det andre eksemplet enn den første. Husk at formålet med å bruke kommandorammen og scenerammen er ikke å oppnå det samme resultatet med mindre kode, men å håndtere koden i en systematisk og modulær tilnærming, noe som gjør livet ditt lettere når det gjelder fremtidig vedlikehold og modifikasjon.

Det første eksemplet klemmer hele koden til en enkelt klasse, noe som gjør det vanskelig for fremtidig vedlikehold dersom kodenes mengde skal vokse ekstremt stor. Det andre eksempelet skiller på den annen side logisk uavhengig kode i forskjellige scener, noe som gjør det lettere for fremtidig modifikasjon. Ved å integrere med kommandorammen og scenerammen har vi også gjort rom for fremtidig utvidelse, der vi kan legge til flere scener og intro / outro kommandoer uten å forstyrre irrelevant kode.

!