在flash6及以前,我们会常常碰到从外部加载一张图片或一段文本,但对于数据何时加载完成/成功,需要通过特殊的方法完成,比如在文本末尾加上特殊的标记,再使用循环检测,当读取到此标记时,认为数据加载完成/成功。
当然这些问题,在as2.0中,已经不存在了,不管加载图片还是外部文本,一般均有 onLoadComplete, onLoadProgress, OnComplete等事件来侦听加载过程或完成动作。
今天要说的,是我们如何在自定义的Class中,自定义自己的事件。比如,我们有自己的一个类,里面封装了使用Remoting从数据库读取一些数据的操作,当数据读取完成时,Remoting的ResultEvent或FaultEvent会被执行。那么这时候,我们如何通过类的事件的方式,再把此结果返回给实例化此类的脚本段呢,这样以使代码看起来更优美,更OO,更准确。
下面,以一个例子来说明自定义事件的使用,演示此示例,需要Flash8+Remoting+.Net FrameWork+IIS,请确保您具有这些先决条件。
一、在IIS中创建虚拟目录YaoGame,设置.net版本为1.1或2.0均可;
二、将Flash Remoting For .net安装到此虚拟目录,或者此目录中有文件:
bin\flashgateway.dll
bin\frconfig.txt
gateway.aspx
web.config
GetData.aspx
(这几个文件,您可以从本文后边下载,直接复制即可,做过Remoting开发的朋友,自然会知道其用处。)
注意 Web.config中
<
httpModules
>
< add name ="GatewayController" type ="FlashGateway.Controller.GatewayController,flashgateway" />
</ httpModules >
< add name ="GatewayController" type ="FlashGateway.Controller.GatewayController,flashgateway" />
</ httpModules >
GetData.aspx内容如下:
<%
@ Page Language
=
"
c#
"
Debug
=
"
true
"
%>
<% @ Register TagPrefix = " Macromedia " Namespace = " FlashGateway " Assembly = " flashgateway " %>
<% @ Import Namespace = " System.Data " %>
< Macromedia:Flash ID = " Flash1 " runat = " Server " />
< script language = " C# " runat = " server " >
void Page_Load(Object sender, EventArgs e)
{
// =========================================================
// Author: Joseph.Yao(http://yao.cnblogs.com)
// Create Date:2007-7-18 22:21:27
// =========================================================
if (Flash1.Params.Count > 0 )
{
if (Flash1.Params[ 0 ] == null )
{
Flash1.Result = " Hello World. " ;
}
else
{
Flash1.Result = " Hello " + Flash1.Params[ 0 ].ToString() + " . " ;
}
}
}
</ script >
<% @ Register TagPrefix = " Macromedia " Namespace = " FlashGateway " Assembly = " flashgateway " %>
<% @ Import Namespace = " System.Data " %>
< Macromedia:Flash ID = " Flash1 " runat = " Server " />
< script language = " C# " runat = " server " >
void Page_Load(Object sender, EventArgs e)
{
// =========================================================
// Author: Joseph.Yao(http://yao.cnblogs.com)
// Create Date:2007-7-18 22:21:27
// =========================================================
if (Flash1.Params.Count > 0 )
{
if (Flash1.Params[ 0 ] == null )
{
Flash1.Result = " Hello World. " ;
}
else
{
Flash1.Result = " Hello " + Flash1.Params[ 0 ].ToString() + " . " ;
}
}
}
</ script >
三、创建一个TestClass 类,内容如下:
import mx.remoting.Service;
import mx.remoting.PendingCall;
import mx.remoting.RecordSet;
import mx.rpc.RelayResponder;
import mx.rpc.ResultEvent;
import mx.rpc.FaultEvent;
import mx.remoting.debug.NetDebug;
// NetDebug.initialize();
import mx.services.Log;
/* *
*
* @Author:Joseph.Yao
* @Version:xx.x.x
* @Create Date:2007-07-18
* @Description:as2.0中自定义事件Demo。
*
* */
class TestClass {
var gatewayPath:String;
var nickName;
// 构造函数
function TestClass() {
// 初始化网关地址
gatewayPath = " http://localhost/YaoGame/gateway.aspx " ;
}
function RemoteData(resultFun:String, faultFun:String) {
//
// 通过Remoting读取数据,但无法估计多久能返回
//
//注意这里的YaoGame应该与虚拟目录一致
// 这三行是Remoting从.net程序加载数据,调用是的http://localhost/YaoGame/GetData.aspx
var myResponder = new RelayResponder( this , resultFun, faultFun);
// 记录日志:var service:Service = new Service(gatewayPath, new Log(), "YaoGame", null, myResponder);
var service:Service = new Service(gatewayPath, null , " YaoGame " , null , myResponder);
var pc:PendingCall = service.GetData( this .nickName);
}
// Remoting成功返回数据时,此方法执行
function Remote_Result(evt:ResultEvent):Void {
//
// {此处可对加载的数据(evt.result)处理}
//
// 当加载成功时,发出事件消息,success值为true
Complete( true , String(evt.result));
}
// Remoting返回数据出错时,此方法执行
function Remote_Fault(evt:FaultEvent):Void {
trace( " 加载数据失败: " + evt.fault.faultstring);
// 当加载失败时,也发出事件消息,但success值为false,
Complete( false , " Load Data Error. " );
}
// 某个费时的操作,无法预知多久可以完成操作,比如从数据库读取数据
function DoSomething(nickName:String) {
this .nickName = nickName;
RemoteData( " Remote_Result " , " Remote_Fault " );
}
// 通过自定义事件,将成功消息和数据"广播"出去
function Complete(success:Boolean, msg:String) {
obj.OnComplete(success, msg);
}
//
// ======================事件==========================
//
private var obj;
// 当某费时操作完成时发生的事件,其实是一个as2.0类的属性,只是属性传递的是一个function类型对象;
public function set OnComplete(fun:Object):Void {
//注意这里的new,如果您是把当前类“链接”到库中的mc上,则这里要稍微注意,不用new有可能会出现你不想要的效果。
//最好的方式是每次事件“委托”的时候,都实例化一个obj出来;
obj = new Object();
obj.OnComplete = fun;
}
}
import mx.remoting.PendingCall;
import mx.remoting.RecordSet;
import mx.rpc.RelayResponder;
import mx.rpc.ResultEvent;
import mx.rpc.FaultEvent;
import mx.remoting.debug.NetDebug;
// NetDebug.initialize();
import mx.services.Log;
/* *
*
* @Author:Joseph.Yao
* @Version:xx.x.x
* @Create Date:2007-07-18
* @Description:as2.0中自定义事件Demo。
*
* */
class TestClass {
var gatewayPath:String;
var nickName;
// 构造函数
function TestClass() {
// 初始化网关地址
gatewayPath = " http://localhost/YaoGame/gateway.aspx " ;
}
function RemoteData(resultFun:String, faultFun:String) {
//
// 通过Remoting读取数据,但无法估计多久能返回
//
//注意这里的YaoGame应该与虚拟目录一致
// 这三行是Remoting从.net程序加载数据,调用是的http://localhost/YaoGame/GetData.aspx
var myResponder = new RelayResponder( this , resultFun, faultFun);
// 记录日志:var service:Service = new Service(gatewayPath, new Log(), "YaoGame", null, myResponder);
var service:Service = new Service(gatewayPath, null , " YaoGame " , null , myResponder);
var pc:PendingCall = service.GetData( this .nickName);
}
// Remoting成功返回数据时,此方法执行
function Remote_Result(evt:ResultEvent):Void {
//
// {此处可对加载的数据(evt.result)处理}
//
// 当加载成功时,发出事件消息,success值为true
Complete( true , String(evt.result));
}
// Remoting返回数据出错时,此方法执行
function Remote_Fault(evt:FaultEvent):Void {
trace( " 加载数据失败: " + evt.fault.faultstring);
// 当加载失败时,也发出事件消息,但success值为false,
Complete( false , " Load Data Error. " );
}
// 某个费时的操作,无法预知多久可以完成操作,比如从数据库读取数据
function DoSomething(nickName:String) {
this .nickName = nickName;
RemoteData( " Remote_Result " , " Remote_Fault " );
}
// 通过自定义事件,将成功消息和数据"广播"出去
function Complete(success:Boolean, msg:String) {
obj.OnComplete(success, msg);
}
//
// ======================事件==========================
//
private var obj;
// 当某费时操作完成时发生的事件,其实是一个as2.0类的属性,只是属性传递的是一个function类型对象;
public function set OnComplete(fun:Object):Void {
//注意这里的new,如果您是把当前类“链接”到库中的mc上,则这里要稍微注意,不用new有可能会出现你不想要的效果。
//最好的方式是每次事件“委托”的时候,都实例化一个obj出来;
obj = new Object();
obj.OnComplete = fun;
}
}
四、创建一个 CustomEventDemo.fla,以测试此类,在此fla时间轴第一帧中加入使用此类的代码:
var
tc
=
new
TestClass();
//这里是给类实例的OnComplete事件指定一个事件执行过程,即当数据完成时,此函数内的脚本被执行,并且数据被返回;
tc.OnComplete = function (success:Boolean, msg:String) {
//success是数据加载是否成功,msg是返回的数据.
trace(success);
trace(msg);
};
tc.DoSomething( " Joseph.yao " );
//执行成功后,返回:
//true
//Hello Joseph.yao.
//这里是给类实例的OnComplete事件指定一个事件执行过程,即当数据完成时,此函数内的脚本被执行,并且数据被返回;
tc.OnComplete = function (success:Boolean, msg:String) {
//success是数据加载是否成功,msg是返回的数据.
trace(success);
trace(msg);
};
tc.DoSomething( " Joseph.yao " );
//执行成功后,返回:
//true
//Hello Joseph.yao.
最后运行 CustomEventDemo.fla文件看测试结果。
五、以上代码中对自定义事件的使用已做了较详细说明了,加黑加粗部分是关键的几处代码。其实这个示例的自定义事件,同时只能挂接一个事件,即所谓单播,如果要实现事件的多播,则稍微要复杂一些,可以通过维护一个事件列表来做,希望有机会和大家探讨。
还有注意测试此示例时,注意Flash的安全策略问题,应该在 http://localhost/根下有一个crossdomain.xml文件来授权可来访的域,否则看不到结果就郁闷了。
本文示例源码完整下载(33K): /Files/yao/as2CustomEventDemo.rar