分享
 
 
 

Flash V2组件基础件开发:ActionRegistry消息分派器。

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

需求

在一个小型客户端项目中,为了美化界面,除了网络连接、数据逻辑处理部分用VC实现以外,显示部分都使用Flash,速度要求不高,用Flash的好处是可以做出一些效果,而且美工可以只负责美工,程序员编写一些简单的Flash Action配合一下即可。

这是一个简单的Flash应用,半天时间就已经完成了。进入测试,通过所有要求。

随之而来的是版本升级问题,最初的简单版本经过3次升级,加上美工参与代码维护以后,基本上原来的代码已经散乱不堪,BUG开始涌现,维护问题突显。

原本打算抽调一名程序员协助美工完成脚本代码维护,不过最终没安排过来。美工自己显然已经不知道自己把代码改成什么样了,也找不出BUG出在什么地方。

程序工作的流程很简,从网络接收的数据经过简单分析处理,最终被分解为简单的“action”(实际上我们把它称为消息),传递给Flash,由它解释成显示数据。初期因为每个action只驱动一个显示动作,所以工作得很好,代码也很整齐。后来升级以后,美工介入编码,由于没有系统结构意识,在“一个Action驱动多个显示动作”时采用了愚蠢的“补贴”方式,致使每个处理action的函数都臃肿不堪,最终导致了蜘蛛网似的代码结构,全局变量(Flash中的绝对路径)到处使用,一个小的改动都可能使显示全部错误。

我开始思考解决办法。

美工的编码方式很简单但也不能说错误,他们有一套自己的编码方式,在短时间内强行去改变他们是没有意义的,让程序员参与编码不但浪费人力,反而让他们双方都觉得进度缓慢,唯一可行的方式是顺着美工的方向走。大致看了一下他们的代码,从网上抄过来的特效代码比较多,只是结构稍差,但并非不可行。

我首先要求美工:每一个小的显示部件单独开发,在一个独立的文件中做好、测试好,并且要保证在各个路径层次上执行正常(减少他们使用全局路径,最终确定了只使用一个全局路径以方便维护)。他们做这些没有任何问题,完成速度也很快。

然后我把这些小部分要用到的action分析了一下,基本上还是我们原来那些action,现在的要求是把这些action送达这些小部件中以进行处理。

问题明确了:每个action由数个不同的小部件侦听,只要写好这个类,并由这些部件注册侦听器即可。

功能描述

因为是在VC中发送这些action,为了在Flash脚本中处理简单一些,我们在VC中驱动Flash显示的代码统一形式为:

m_wndFlash.SetVariable (“_root.action_processor.action“, “action_type:action_body“);

第一个参数是action处理器组件的一个setter函数,后面的字符串就是传递给它处理的。因为在VC中无法直接调用组件的函数,只能用这种方式间接调用。根据这个约定,我在原来的基础上编写了ActionRegistry类,为了美工调用方便,做成了一个可视组件,实际上并不负责显示,只是方便他把组件拖到场景中并取个名字。

实现

实现过程并没有太复杂,所以我直接把代码发上来了。

class biz.blueskytech.ActionRegistry

{

private var _action_listenerlist_map : Object;

function ActionRegistry ()

{

_action_listenerlist_map = {};

}

function registryListener (type:String, obj:Object) : Void

{

if (_action_listenerlist_map[type] == undefined)

_action_listenerlist_map[type] = new Array ();

_action_listenerlist_map[type].push (obj);

}

function removeListener (type:String, obj:Object) : Void

{

var arr = _action_listenerlist_map[type];

if (arr != undefined)

{

for (var i=0; i<arr.length; i++)

if (arr[i] == obj)

arr.splice (i, 1);

}

}

function dispatchAction (type:String, args:Array) : Void

{

var arr = _action_listenerlist_map[type];

if (arr != undefined)

{

for (var i=0; i<arr.length; i++)

{

var obj = arr[i];

var funcName = "on" + type.charAt(0).toUpperCase () + type.substr (1);

if (typeof (obj[funcName]) == "function")

obj[funcName].apply (obj, args);

else

trace ("the listener not implement "+type+" handle");

}

}

else

{

trace ("action "+type+" no listeners");

}

}

function set action (str:String) : Void

{

if (str != undefined)

{

var delimiter_pos = str.indexOf (":");

if (delimiter_pos > 0)

{

var action_type = str.substr (0, delimiter_pos);

var action_body = str.substr (delimiter_pos+1);

if (action_type.length > 0)

{

//trace ("call listeners handler of action {"+action_type+"}");

var args = parse_body (action_type, action_body);

dispatchAction (action_type, args);

}

else

{

trace ("invalid action type or args");

}

}

else

{

trace ("invalid action format");

}

}

else

{

trace ("invalid action call");

}

}

function parse_body (type:String, body:String) : Array

{

var funcName = type+"Handler";

if (typeof (this[funcName]) == "function")

return this[funcName].apply (this, [body]);

else

{

trace ("action handler not found");

return [];

}

}

}

至于怎么生成组件,不是本文的重点,只要用一个空的MovieClip和它链接,并定义组件即可,是否导出编译组件并不重要。

调用实例

新建一个Flash文件,在里面加入一个ActionRegistry组件实例,命名为action_registry。

在第一桢加入下面的代码:

action_registry.testHandler = function (t:String):Array

{

return [5,4];

}

以上代码是为action_registry加入test消息的解析函数,用它来把消息解析成参数,供侦听回调函数使用。下面代码注册了2个侦听器,它们有不同的处理函数:

var obj = new Object ();

obj.onTest = function (t1:Number, t2:Number)

{

trace ("T1: "+t1);

trace ("T2: "+t2);

}

action_registry.registryListener ("test", obj);

var obj1 = new Object ();

obj.onTest = function (t1:Number, t2:Number)

{

trace (“Result: “+(t1+t2));

}

action_registry.registryListener ("test", obj1);

初始化就完成了。我们现在加入一个按钮,给它的click(或是release)事件编写代码:

on (click)

{

_root.action_registry.action = "test:0";

}

因为test消息的参数我们并没有用到,实际上从引号后面就可以空差。现在测试影片吧,你应该可以看到2个消息处理函数都执行了,这也达到了本文的要求。

如果你知道怎么在VC中给影片中的变量赋值,你自然会明白这个组件给你带来了什么——一个多路消息分派器。

如果你只是在Flash中使用此分派器,则无需先将消息格式化为字符串,可以直接调用:

_root.action_registry.dispatchAction (”test”, [5,4]);

这样做也提高了效率。

测试总结

现在我们只要在要侦听这个消息的地方去注册侦听器即可,对代码层次、调用顺序没有任何影响,很好地达到了要求。

本文也使用了一些Flash V2组件脚本的新语法。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有