使用异步数据提供程序对象时,IFilePromise
isAsync
属性必须为
true
,并且由
open()
方法返回的对象必须实现 IEventDispatcher 接口。运行时侦听多个替代事件,以便可以使用不同的内置对象作为数据提供程序。例如,
progress
事件由 FileStream 和 URLStream 对象调度,而
socketData
事件由 Socket 对象调度。运行时从所有这些对象侦听适当的事件。
下列事件推动从数据提供程序对象读取数据的进程:
-
Event.OPEN — 通知运行时数据源已准备好。
-
ProgressEvent.PROGRESS — 通知运行时数据可用。运行时将从数据提供程序对象读取可用的数据量。
-
ProgressEvent.SOCKET_DATA — 通知运行时数据可用。
socketData
事件由基于 Socket 的对象调度。对于其他对象类型,您应调度
progress
事件。(运行时同时侦听这两个事件以检测何时可以读取数据。)
-
Event.COMPLETE — 通知运行时已读取所有数据。
-
Event.CLOSE — 通知运行时已读取所有数据。(运行时同时侦听
close
和
complete
来实现此目的。)
-
IOErrorEvent.IOERROR — 通知运行时读取数据时出错。运行时终止文件创建并调用 IFilePromise
close()
方法。
-
SecurityErrorEvent.SECURITY_ERROR — 通知运行时出现安全性错误。运行时终止文件创建并调用 IFilePromise
close()
方法。
-
HTTPStatusEvent.HTTP_STATUS — 运行时同时使用它和
httpResponseStatus
,以确保可用数据表示所需内容,而不会显示错误消息(例如 404 页面)。基于 HTTP 协议的对象应调度此事件。
-
HTTPStatusEvent.HTTP_RESPONSE_STATUS — 运行时同时使用它和
httpStatus
,以确保可用数据表示所需内容。基于 HTTP 协议的对象应调度此事件。
数据提供程序应按照以下顺序调度这些事件:
-
open
事件
-
progress
或
socketData
事件
-
complete
或
close
事件
注:
内建对象(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 );
}
}
}