非同期データプロバイダーオブジェクトを使用するときは、IFilePromise の
isAsync
プロパティを
true
に設定し、
open()
メソッドによって返されるオブジェクトに IEventDispatcher インターフェイスを実装する必要があります。様々なビルトインオブジェクトをデータプロバイダーとして使用できるように、ランタイムは複数の代替イベントを監視します。例えば、
progress
イベントは FileStream オブジェクトおよび URLStream オブジェクトによって送出され、
socketData
イベントは Socket オブジェクトによって送出されます。ランタイムは、これらすべてのオブジェクトから適切なイベントを監視します。
次の各イベントは、データプロバイダーオブジェクトからのデータの読み取りプロセスを制御します。
-
Event.OPEN — データソースの準備が完了していることをランタイムに通知します。
-
ProgressEvent.PROGRESS — データが使用可能であることをランタイムに通知します。ランタイムは、使用可能なデータの量をデータプロバイダーオブジェクトから読み取ります。
-
ProgressEvent.SOCKET_DATA — データが使用可能であることをランタイムに通知します。
socketData
イベントはソケットベースのオブジェクトによって送出されます。その他のオブジェクトタイプについては、
progress
イベントを送出する必要があります(ランタイムは両方のイベントを監視してデータの読み取りが可能なタイミングを検出します)。
-
Event.COMPLETE — データがすべて読み込まれたことをランタイムに通知します。
-
Event.CLOSE — データがすべて読み込まれたことをランタイムに通知します(この場合、ランタイムは
close
と
complete
の両方を監視します)。
-
IOErrorEvent.IOERROR — データの読み取りエラーが発生したことをランタイムに通知します。ランタイムはファイル作成を中止し、IFilePromise の
close()
メソッドを呼び出します。
-
SecurityErrorEvent.SECURITY_ERROR — セキュリティエラーが発生したことをランタイムに通知します。ランタイムはファイル作成を中止し、IFilePromise の
close()
メソッドを呼び出します。
-
HTTPStatusEvent.HTTP_STATUS — 使用可能なデータがエラーメッセージ(404 ページなど)ではなく必要なコンテンツを表していることを確認するために、
httpResponseStatus
と共にランタイムによって使用されます。このイベントは HTTP プロトコルに基づくオブジェクトによって送出されます。
-
HTTPStatusEvent.HTTP_RESPONSE_STATUS — 使用可能なデータが必要なコンテンツを表していることを確認するために、
httpStatus
と共にランタイムによって使用されます。このイベントは HTTP プロトコルに基づくオブジェクトによって送出されます。
データプロバイダーでは、これらのイベントが次の順序で送出されます。
-
open
イベント
-
progress
イベントまたは
socketData
イベント
-
complete
イベントまたは
close
イベント
注意:
ビルトインオブジェクト、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 );
}
}
}