实现 IFilePromise 接口Adobe AIR 2 和更高版本 若要为不能使用 URLFilePromise 对象访问的资源提供文件释放,可以在自定义类中实现 IFilePromise 接口。一旦放置文件释放后,IFilePromise 接口就会定义由 AIR 运行时访问要写入到文件中的数据所用的方法和属性。 IFilePromise 实现将为该文件释放提供数据的另一个对象传递到 AIR 运行时。此对象必须实现 AIR 运行时用于读取数据的 IDataInput 接口。例如,可实现 IFilePromise 的 URLFilePromise 类使用 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 );
}
}
}
实际上,同步文件释放的效用很受限。如果数据量很小,您可以在临时目录中轻松创建一个文件,将普通文件列表数组添加到拖放剪贴板。另一方面,如果数据量很大或生成数据的计算成本很高,则长的同步进程是必需的。长的同步进程会在明显较长的时间内阻止 UI 更新,使应用程序看起来像无响应一样。若要避免此问题,您可以创建一个由计时器驱动的异步数据提供程序。 在文件释放中使用异步数据提供程序使用异步数据提供程序对象时,IFilePromise isAsync 属性必须为 true,并且由 open() 方法返回的对象必须实现 IEventDispatcher 接口。运行时侦听多个替代事件,以便可以使用不同的内置对象作为数据提供程序。例如,progress 事件由 FileStream 和 URLStream 对象调度,而 socketData 事件由 Socket 对象调度。运行时从所有这些对象侦听适当的事件。 下列事件推动从数据提供程序对象读取数据的进程:
数据提供程序应按照以下顺序调度这些事件:
注: 内建对象(FileStream、Socket 和 URLStream)自动调度相应的事件。
以下示例使用自定义异步数据提供程序创建一个文件释放。数据提供程序类扩展了 ByteArray(以实现 IDataInput 支持)并实现 IEventDispatcher 接口。在每个 timer 事件发生时,对象会生成大量数据,并调度 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 );
}
}
}
|
|