Реализация интерфейса IFilePromiseAdobe AIR 2 и более новых версий Чтобы предоставить предварительные образы файла для ресурсов, доступ к которым с помощью объекта URLFilePromise невозможен, можно реализовать интерфейс IFilePromise в пользовательском классе. Интерфейс IFilePromise определяет методы и свойства, используемые средой выполнения AIR для доступа к данным, которые необходимо записать в файл после перетаскивания предварительного образа файла. Реализация IFilePromise передает другой объект среде выполнения AIR, которая предоставляет данные для предварительного образа файла. Этот объект должен реализовать интерфейс IDataInput, который применяется средой выполнения AIR для чтения данных. Например, класс URLFilePromise, реализующий IFilePromise, использует в качестве поставщика данных объект URLStream. AIR может синхронно или асинхронно считывать данные. Реализация IFilePromise сообщает о поддерживаемом режиме доступа путем возврата соответствующего значения в свойство isAsync. Если предоставляется асинхронный доступ к данным, объект поставщика данных должен реализовать интерфейс IEventDispatcher и отправить необходимые события (такие как open, progress и complete). Можно воспользоваться пользовательским классом, либо одним из следующих встроенных классов в качестве поставщика данных для предварительного образа файла:
Чтобы реализовать интерфейс IFilePromise, необходимо предоставить код для следующих функций и свойств.
Все методы IFilePromise вызываются средой выполнения во время операции перетаскивания, включающей предварительный образ файла. Как правило, ваша логика приложения не должна вызывать какие-либо из этих методов напрямую. Использование синхронного поставщика данных в предварительном образе файлаСамый простой способ реализации интерфейса IFilePromise состоит в том, чтобы использовать объект синхронного поставщика данных (например, ByteArray или синхронный FileStream). В следующем примере создается заполненный данными объект ByteArray, который возвращается при вызове метода 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 );
}
}
}
На практике синхронные предварительные образы файла имеют ограниченное применение. Если данных мало, можно с легкостью создать файл во временном каталоге и добавить обычный массив со списком файлов в буфер обмена при перетаскивании. С другой стороны, если объем данных велик или генерирование данных требует больших вычислительных ресурсов, требуется продолжительный синхронный процесс. Продолжительные синхронные процессы могут блокировать обновления пользовательского интерфейса в течение заметного периода времени и создавать впечатление «зависания» программы. Во избежание появления этой проблемы можно создать асинхронный поставщик данных, который включается таймером. Использование асинхронного поставщика данных в предварительном образе файлаПри использовании объекта асинхронного поставщика данных свойству isAsync интерфейса IFilePromise должно быть присвоено значение true, а объект, возвращенный методом open(), должен реализовать интерфейс IEventDispatcher. Среда выполнения прослушивает несколько альтернативных событий, чтобы в качестве поставщика данных можно было использовать разные встроенные объекты. Например, события progress отправляются объектами FileStream и URLStream, а события socketData отправляются объектами Socket. Среда выполнения прослушивает соответствующие события из всех этих объектов. Процесс считывания данных из объекта поставщика данных зависит от следующих событий.
Поставщик данных должен отправлять эти события в следующей последовательности:
Примечание. Встроенные объекты (FileStream, Socket и URLStream) автоматически отправляют соответствующие события.
В следующем примере предварительный образ файла создается с помощью пользовательского асинхронного поставщика данных. Класс поставщика данных является расширением ByteArray (для поддержки IDataInput) и реализует интерфейс IEventDispatcher. При каждом событии таймера объект генерирует порцию данных и отправляет событие progress, чтобы сообщить среде выполнения о доступности данных. После получения достаточного объема данных объект отправляет событие complete. 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 );
}
}
}
Примечание. Поскольку класс AsyncDataProvider в данном примере является расширением ByteArray, он не может также являться расширением EventDispatcher. Чтобы реализовать интерфейс IEventDispatcher, класс использует внутренний объект EventDispatcher и перенаправляет вызовы метода IEventDispatcher в этот внутренний объект. Можно также расширить EventDispatcher и реализовать IDataInput (или реализовать оба интерфейса).
Асинхронная реализация интерфейса IFilePromise почти идентична синхронной реализации. Основные различия состоят в том, что isAsync возвращает true и что метод open() возвращает объект асинхронных данных: 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 );
}
}
}
|
|