Implementatie van de IFilePromise-interfaceAdobe AIR 2 of hoger Als u bestandsbeloften beschikbaar wilt stellen voor resources die niet via een URLFilePromise-object toegankelijk zijn, kunt u de IFilePromise-interface in een aangepaste klasse implementeren. De IFilePromise-interface definieert de methoden en eigenschappen die in AIR worden gebruikt om toegang te krijgen tot de gegevens die naar een bestand moeten worden geschreven als de bestandsbelofte eenmaal is neergezet. Een IFilePromise-implementatie geeft in AIR nog een object door dat de gegevens voor de bestandsbelofte levert. De IDataInput-interface moet door dit object worden geïmplementeerd. Deze interface wordt in AIR gebruikt om de gegevens te lezen. De URLFilePromise-klasse bijvoorbeeld, waardoor IFilePromise wordt geïmplementeerd, gebruikt een URLStream-object als de gegevensaanbieder. AIR kan de gegevens synchroon of asynchroon lezen. De IFilePromise-implementatie rapporteert welke toegangsmodus wordt ondersteund door de juiste waarde in de eigenschap isAsync te retourneren. In geval van asynchrone gegevenstoegang moet het gegevensaanbiederobject de IEventDispatcher-interface implementeren en de benodigde gebeurtenissen verzenden, zoals open, progress en complete. U kunt een aangepaste klasse of een van de volgende ingebouwde klassen gebruiken als gegevensaanbieder voor een bestandsbelofte:
Om de IFilePromise-interface te implementeren moet u code voor de volgende functies en eigenschappen leveren:
Alle IFilePromise-methoden worden aangeroepen bij het slepen en neerzetten van een bestandsbelofte. Doorgaans mogen deze methoden niet rechtstreeks door uw toepassingslogica worden aangeroepen. Een synchrone gegevensaanbieder gebruiken in een bestandsbelofteU kunt de IFilePromise-interface het eenvoudigst implementeren met een synchroon gegevensaanbiederobject, zoals een ByteArray of een synchrone FileStream. In het volgende voorbeeld wordt een ByteArray-object gemaakt, gevuld met gegevens en geretourneerd wanneer de methode open() wordt aangeroepen. package { import flash.desktop.IFilePromise; import flash.events.ErrorEvent; import flash.utils.ByteArray; import flash.utils.IDataInput; public class SynchronousFilePromise implements IFilePromise { private const fileSize:int = 5000; //size of file data private var filePath:String = "SynchronousFile.txt"; public function get relativePath():String { return filePath; } public function get isAsync():Boolean { return false; } public function open():IDataInput { var fileContents:ByteArray = new ByteArray(); //Create some arbitrary data for the file for( var i:int = 0; i < fileSize; i++ ) { fileContents.writeUTFBytes( 'S' ); } //Important: the ByteArray is read from the current position fileContents.position = 0; return fileContents; } public function close():void { //Nothing needs to be closed in this case. } public function reportError(e:ErrorEvent):void { trace("Something went wrong: " + e.errorID + " - " + e.type + ", " + e.text ); } } } In de praktijk is het nut van synchrone bestandsbeloften beperkt. Als de hoeveelheid gegevens klein is, kunt u net zo gemakkelijk een bestand in een tijdelijke map maken en een normale bestandenlijstarray aan het klembord voor slepen en neerzetten toevoegen. Aan de andere kant, als de hoeveelheid gegevens groot is of als de computer zwaar wordt belast door het genereren van de gegevens, is een lang synchroon proces nodig. Lange synchrone processen kunnen updates van de gebruikersinterface gedurende een aanzienlijke periode blokkeren. Hierdoor kan het lijken alsof uw toepassing niet reageert. Om dit probleem te vermijden, kunt u een asynchrone gegevensaanbieder maken die wordt aangestuurd door een timer. Een asynchrone gegevensaanbieder gebruiken in een bestandsbelofteAls u een asynchroon gegevensaanbiederobject gebruikt, moet de eigenschap isAsync van IFilePromise zijn ingesteld op true en moet het object dat wordt geretourneerd door de methode open() de IEventDispatcher-interface implementeren. Tijdens runtime wordt er geluisterd of een aantal alternatieve gebeurtenissen plaatsvinden, zodat verschillende ingebouwde objecten als gegevensaanbieder kunnen worden gebruikt. progress-gebeurtenissen worden bijvoorbeeld verzonden door FileStream- en URLStream-objecten, terwijl socketData-gebeurtenissen worden verzonden door Socket-objecten. Tijdens runtime wordt er geluisterd of al deze objecten de juiste gebeurtenissen verzenden. Het lezen van gegevens in het gegevensaanbiederobject wordt door de volgende gebeurtenissen aangestuurd:
De gegevensaanbieder moet deze gebeurtenissen in de volgende volgorde verzenden:
Opmerking: De ingebouwde objecten FileStream, Socket en URLStream verzenden automatisch de juiste gebeurtenissen.
In het volgende voorbeeld wordt een bestandsbelofte gemaakt met een aangepaste asynchrone gegevensaanbieder. De gegevensaanbiederklasse biedt ByteArray uit (voor de ondersteuning voor IDataInput) en implementeert de IEventDispatcher-interface. Bij elke timer-gebeurtenis genereert het object een hoeveelheid gegevens en verzendt het object een progress-gebeurtenis om tijdens runtime te melden dat de gegevens beschikbaar zijn. Als er genoeg gegevens zijn gegenereerd, verzendt het object een complete-gebeurtenis. package { import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IEventDispatcher; import flash.events.ProgressEvent; import flash.events.TimerEvent; import flash.utils.ByteArray; import flash.utils.Timer; [Event(name="open", type="flash.events.Event.OPEN")] [Event(name="complete", type="flash.events.Event.COMPLETE")] [Event(name="progress", type="flash.events.ProgressEvent")] [Event(name="ioError", type="flash.events.IOErrorEvent")] [Event(name="securityError", type="flash.events.SecurityErrorEvent")] public class AsyncDataProvider extends ByteArray implements IEventDispatcher { private var dispatcher:EventDispatcher = new EventDispatcher(); public var fileSize:int = 0; //The number of characters in the file private const chunkSize:int = 1000; //Amount of data written per event private var dispatchDataTimer:Timer = new Timer( 100 ); private var opened:Boolean = false; public function AsyncDataProvider() { super(); dispatchDataTimer.addEventListener( TimerEvent.TIMER, generateData ); } public function begin():void{ dispatchDataTimer.start(); } public function end():void { dispatchDataTimer.stop(); } private function generateData( event:Event ):void { if( !opened ) { var open:Event = new Event( Event.OPEN ); dispatchEvent( open ); opened = true; } else if( position + chunkSize < fileSize ) { for( var i:int = 0; i <= chunkSize; i++ ) { writeUTFBytes( 'A' ); } //Set position back to the start of the new data this.position -= chunkSize; var progress:ProgressEvent = new ProgressEvent( ProgressEvent.PROGRESS, false, false, bytesAvailable, bytesAvailable + chunkSize); dispatchEvent( progress ) } else { var complete:Event = new Event( Event.COMPLETE ); dispatchEvent( complete ); } } //IEventDispatcher implementation public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void { dispatcher.addEventListener( type, listener, useCapture, priority, useWeakReference ); } public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void { dispatcher.removeEventListener( type, listener, useCapture ); } public function dispatchEvent(event:Event):Boolean { return dispatcher.dispatchEvent( event ); } public function hasEventListener(type:String):Boolean { return dispatcher.hasEventListener( type ); } public function willTrigger(type:String):Boolean { return dispatcher.willTrigger( type ); } } } Opmerking: Omdat de AsyncDataProvider-klasse in het voorbeeld ByteArray uitbreidt, kan deze klasse niet tevens EventDispatcher uitbreiden. Om de IEventDispatcher-interface te implementeren, gebruikt de klasse een intern EventDispatcher-object en stuurt de IEventDispatcher-methode aanroepen door naar dat interne object. U kunt eventueel ook EventDispatcher uitbreiden en IDataInput implementeren (of beide interfaces implementeren).
De asynchrone IFilePromise-implementatie is bijna identiek aan de synchrone implementatie. De belangrijkste verschillen zijn dat isAsynctrue retourneert en dat de methode open() een asynchroon gegevensobject retourneert: package { import flash.desktop.IFilePromise; import flash.events.ErrorEvent; import flash.events.EventDispatcher; import flash.utils.IDataInput; public class AsynchronousFilePromise extends EventDispatcher implements IFilePromise { private var fileGenerator:AsyncDataProvider; private const fileSize:int = 5000; //size of file data private var filePath:String = "AsynchronousFile.txt"; public function get relativePath():String { return filePath; } public function get isAsync():Boolean { return true; } public function open():IDataInput { fileGenerator = new AsyncDataProvider(); fileGenerator.fileSize = fileSize; fileGenerator.begin(); return fileGenerator; } public function close():void { fileGenerator.end(); } public function reportError(e:ErrorEvent):void { trace("Something went wrong: " + e.errorID + " - " + e.type + ", " + e.text ); } } } |
![]() |