Implementação da interface IFilePromiseAdobe AIR 2 e posterior Para fornecer promessas de arquivo para os recursos que não podem ser acessados com um objeto URLFilePromise, você pode implementar a interface IFilePromise em uma classe personalizada. A interface IFilePromise define os métodos e propriedades usados pelo tempo de execução do AIR para acessar os dados a serem gravados em um arquivo depois que a promessa é solta. Uma implementação IFilePromise passa outro objeto ao tempo de execução do AIR que fornece os dados para a promessa de arquivo. Esse objeto deve implementar a interface IDataInput, que o tempo de execução do AIR usa para ler os dados. Por exemplo, a classe URLFilePromise, que implementa IFilePromise, usa um objeto URLStream como fornecedor dos dados. O AIR pode ler os dados de forma síncrona ou assíncrona. A implementação IFilePromise informa qual modo de acesso é suportado ao devolver o valor apropriado na propriedade isAsync. Se for fornecido acesso aos dados assíncronos, o objeto do fornecedor de dados deve implementar a interface IEventDispatcher e despachar os eventos necessários, como open, progress e complete. Você pode usar uma classe personalizada ou uma das classes incorporadas seguintes, como fornecedor de dados para uma promessa de dados:
Para implementar a interface IFilePromise, você deve fornecer o código para as funções e propriedades seguintes:
Todos os métodos IFilePromise são chamados pelo tempo de execução durante uma operação de arrastar e soltar envolvendo a promessa de arquivo. Em geral, sua lógica de aplicativo não deve chamar nenhum desses métodos diretamente. Uso do fornecedor de dados síncrono em uma promessa de arquivoA forma mais simples de implementar a interface IFilePromise é usar um objeto de fornecedor de dados síncrono, como ByteArray ou um FileStream síncrono. No exemplo a seguir, é criado um objeto ByteArray, preenchido com dados e retornado quando se chama o método open(). 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 );
}
}
}
Na prática, as promessas de arquivo síncronas têm utilidade limitada. Se a quantidade de dados for pequena, você poderia facilmente criar um arquivo em um diretório temporário e acrescentar uma matriz normal da lista de arquivos à área de transferência de arrastar e soltar. Por outro lado, se a quantidade de dados for grande ou for caro gerar os dados de forma computacional, é necessário um processo síncrono longo. Os processos síncronos longos podem bloquear as atualizações de UI por um tempo notável e fazer com que seu aplicativo pareça não responder. Para evitar este problema, você pode criar um fornecedor de dados assíncronos orientado por um cronômetro. Uso do fornecedor de dados assíncrono em uma promessa de arquivoAo usar um objeto de fornecedor de dados assíncrono, a propriedadeisAsync do IFilePromise deve ser true e o objeto devolvido pelo método open() deve implementar a interface IEventDispatcher. O tempo de execução ouve os vários eventos alternativos de forma que se possam usar objetos incorporados diferentes como fornecedor de dados. Por exemplo, os eventos progress são despachados pelos objetos FileStream e URLStream, ao passo que os eventos socketData são despachados pelos objetos Socket. O tempo de execução ouve os eventos apropriados de todos esses objetos. Os eventos a seguir orientam o processo de leitura de dados do objeto do fornecedor de dados:
O fornecedor de dados deve despachar esses eventos na sequência a seguir:
Nota: Os objetos incorporados, FileStream, Socket e URLStream, despacham os eventos apropriados automaticamente.
O exemplo a seguir cria uma promessa de arquivo usando um fornecedor de dados personalizado e assíncrono. A classe do fornecedor de dados extende ByteArray (para o suporte do IDataInput) e implementa a interface IEventDispatcher. No evento de cada cronômetro, o objeto gera um pouco de dados e despacha um evento progress para informar ao tempo de execução que os dados estão disponíveis. Quando forem produzidos dados suficientes, o objeto despacha um evento completo. 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 );
}
}
}
Nota: Como a classe AsyncDataProvider no exemplo estende ByteArray, ela não pode estender também o EventDispatcher. Para implementar a interface IEventDispatcher, a clase usa um objeto EventDispatcher interno e encaminha as chamadas do método IEventDispatcher para aquele objeto interno. Você também poderia estender o EventDispatcher e implementar IDataInput (ou implementar as duas interfaces).
A implementação assíncrona de IFilePromise é quase idêntica à implementação síncrona. As principais diferenças são que isAsync retorna true e que o método open() retorna um objeto de dados assíncrono: 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 );
}
}
}
|
|