- 浏览: 153487 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
秃鹰路:
在哪下载。找不到下载点怎么
mac 下 Flash Builder 4.7 破解 -
whlei01:
我是照着做的 但是在ControlBtnsMediator中的 ...
flex框架pureMVC的使用:第一步 -
neusoft_jerry:
beijixingzhi 写道距离作者发帖都好几年了,不知道还 ...
flex框架pureMVC的使用:第一步 -
neusoft_jerry:
beijixingzhi 写道距离作者发帖都好几年了,不知道还 ...
flex框架pureMVC的使用:第一步 -
caowanglong1987:
多谢了,哥们
jquery ui dialog 在ie下报错问题解决
做flex做久做大了,使用一个框架便是自然而然的事情。这样程序才会更健壮,更易于扩展,更易于维护。pureMVC足够简单,核心也只有十来个类,是一个轻量级的Flex框架,只一天的时间,就可以学通,没有理由不用它的。
麻雀虽小,五脏俱全,pureMVC,直译过来就是“纯MVC”,是一个MVC框架。官方的中文文档有44页,放在附件中,可以下载了看。推荐一个入门的文章给大家。(http://riachina.com/showtopic-11011.html ),里面有足够全面的介绍。这里我想利用一个更加简单的图片展示的例子来展示pureMVC的使用细节。先看效果:
介绍一下这个应用。程序一开始便请求展示的图片信息(包括图片的链接以及名称),得到信息后便可以通过两个按钮进行逐张的浏览。这个例子太简单了,以致根本没有必要去用pureMVC,这里我只是想借用它来介绍pureMVC如何使用的。
如果将上面的例子假设为做菜,哈哈,就会更有意思了。两个 Button ,一个 Image 与 Label 便是锅碗瓢盆,而图片的信息便是原料,而怎么样来炒,便要看菜谱了。pureMVC 的设计者估计也是做菜的高手。这些对他们来说就是 Model (原料), View (锅碗瓢盆), Controller (菜谱),三个都是单例模式。同时他们还设计出一个厨师,叫 Facade ,由它来调度上面三个,也是单例的。
一切从 Facade 开始,它实列化 Model , View , Controller 。MVC 也找了一些帮手, Model 找到的是 Proxy 们,代理?好像翻译得不对。不管,以后的数据就靠它了。View 找的是 Mediator,它们负责UI,Controller 找的是 Command,不过 Command 性格比较怪,做完一次任务就不干了,也就是短生命同期的。每次用它 pureMVC 都会重新创建。所以只能用它来做业务逻辑,而不要将长期的数据放在里面。
pureMVC 消息采用的观察者模式,每次做完一件事情,就可以向外发出一个 Notification (不是 Flex 里的 Event 哟),就像向外宣布“事情做完了”,具体谁关心就管不着了。这里 Proxy 有点特别,它们只会向外发出 Notification ,但从不接收,只关心自己的数据模型。这很有意义,想想人家叫 “纯MVC” 嘛。
好了,开始做这个例子。刚开始学东西的时候总会发现,文档都看懂了,东西好像都会了。真要用它做东西,却不知道怎么下手。所以还要再好好分析下程序,看看怎么样下手。
首先界面上就四个控件,两个Button ,一个 Image 和 一个Label ,从功能上可以分为两类,两个 Button 是用来作控制的, Image 与 Label 用来显示图片及图片名称。和 UI 对应的是 Mediator ,所以要定义两个 Mediator 类。如果程序变大了,也可以这样来划分,千万不要为每个按钮作一个 Mediator ,也不要整个 Application 才一个 Mediator,最好按功能来划分。
然后再来看 Model ,本例中的数据只有一项,便是要显示的图片资料。所以只要求定义一个 Proxy 用来数据交互就够了。flex 得到数据的方式有许多种,如HttpService ,RemoteObject ,XMLSocket等,但不管什么,总之都是从其他地方得到有用的信息,然后将它变成自己自己的程序能够理解的形式。当然解析数据,大多是业务逻辑( Controller )的工作了。
再看Controller这边,Controller 涉及到业务 ,本例中业务有程序启动(StartUp),还有个就是得到图片信息。还有吗,好像没有了。两个Command就可以应付了。
好了,可以动手编码了。
定义两个Mediator (ImageMediator 与 ControlBtnsMediator,继承Mediator类,实现IMediator接口),
两个Command ( StartUpCommand 与 GetUrlListCommand,继承SimpleCommand类,实现ICommand)
以及一个Proxy (ImageUrlListProxy ,继承Proxy,实现IProxy接口)
一个图片信息类(ImageUrlVO),用来存放单张图片信息。
一个Facade (MyAppFacade 继承Facade,实现IFacade接口)
程序的包结构:
同时思考需要的 Notification ,它是将整个框架联系起来的关键。
1.程序开始便要启动 StrartUpCommand,所以StrartUpCommand 要关注 "app_startup"
2.StrartUpCommand主要完成Proxy与Mediator的注册,完成后便可以启动GetUrlListCommand,所以GetUrlListCommand应关注"app_startup_over"
3.GetUrlListCommand 通过 ImageUrlListProxy去获取图片信息,前面提到 ImageUrlListProxy是不能接收Notification,所以GetUrlListCommand要直接调用ImageUrlListProxy的public成员函数loadUrlList()去获取图片信息
4.ImageUrlListProxy 得到图片链接以后,便可以对外宣布“图片信息已经得到了”,即对外Send一个"url_load_complete"的Notification,关注这一Notification的自然是ImageMediator,它直接将图片信息保存起来,并显示第一张图片内容
5.ControlBtnsMediator不需要关注任何Notification,不过点击两个按钮时会向外Send Notification ("next_image" 与 "prev_image"),,通知显示下一张或上一张图片。关注这两个Notification的自然是ImageMediator了。
好了,流程都介绍完了,来看代码。
先定义类 ImageUrlVO 的代码如下:
package MyApp.Model.VO { public class ImageUrlVO { public var url:String; //图片链接 public var name:String; //图片名称 public function ImageUrlVO(url:String,name:String){ this.url = url; this.name = name; } } }
接下来从程序的执行步骤依次看各个类的代码。
主界面 HelloPureMVC.mxml:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="200" height="200" creationComplete="initApp()"> <mx:Script> <![CDATA[ import MyApp.MyAppFacade; public function initApp():void{ var facade:MyAppFacade = MyAppFacade.getInstance(); facade.startup( this ); } ]]> </mx:Script> <mx:Canvas id="mainContainer" width="100%" height="100%"> <mx:Label id="nameLabel" x="87.5" y="0"/> <mx:Image id="image" x="30" y="20" width="140" height="140"/> <mx:Button x="10" y="168" label="上一张" id="btnPrev"/> <mx:Button x="125" y="168" label="下一张" id="btnNext"/> </mx:Canvas> </mx:Application>
主界面现在只关注布局就够了。同时还要注意到里面的initApp()函数,它首先得到Facade实例,再调用其 startup() 函数启动整个PureMVC框架。
跟进去再让看 MyAppFacade 的实现。
package MyApp { import MyApp.Controller.GetUrlListCommand; import MyApp.Controller.StartUpCommand; import org.puremvc.as3.interfaces.IFacade; import org.puremvc.as3.patterns.facade.Facade; public class MyAppFacade extends Facade implements IFacade { public static const APP_STARTUP:String = "app_startup"; public static const APP_STARTUP_OVER:String = "app_startup_over"; public function MyAppFacade() { super(); } public static function getInstance():MyAppFacade{ if(instance==null) instance = new MyAppFacade(); return instance as MyAppFacade; } override protected function initializeController():void{ super.initializeController(); //register some Commands registerCommand(APP_STARTUP,StartUpCommand); registerCommand(APP_STARTUP_OVER,GetUrlListCommand); } public function startup(app:Object):void{ sendNotification(APP_STARTUP,app); } } }
可见Facade做的事情很简单, initializeController() 是用来初始化Controller的,这个函数是建立各个Notification与Command映射的地方,有了上面的流程分析,
registerCommand(APP_STARTUP,StartUpCommand); registerCommand(APP_STARTUP_OVER,GetUrlListCommand);
这两行这很容易了。startup()函数,终于轮到它了。它只做了一件事情,就是向外派发一个APP_STARTUP的Notification,关注它的是前面已经建立映射的StartUpCommand,pureMVC会实例化一个StartUpCommand的实例,并将app作为参数,调用其execute函数。
tip:通常用一个字符串来标识一个Notification,不过建议用字符常量。减少犯错的可能。
再来看StartUpCommand的代码:
package MyApp.Controller { import MyApp.Model.ImageUrlListProxy; import MyApp.MyAppFacade; import MyApp.View.ControlBtnsMediator; import MyApp.View.ImageMediator; import org.puremvc.as3.interfaces.ICommand; import org.puremvc.as3.interfaces.INotification; import org.puremvc.as3.patterns.command.SimpleCommand; public class StartUpCommand extends SimpleCommand implements ICommand { public function StartUpCommand() { super(); } override public function execute(notification:INotification):void { var app:HelloPureMVC = notification.getBody() as HelloPureMVC; //注册代理(proxy) facade.registerProxy( new ImageUrlListProxy( ImageUrlListProxy.NAME ) ); //注册中介器 facade.registerMediator( new ImageMediator( ImageMediator.NAME, { image:app.image, nameLabel:app.nameLabel } ) ); facade.registerMediator( new ControlBtnsMediator( ControlBtnsMediator.NAME , { btnNext:app.btnNext, btnPrev:app.btnPrev } ) ); //通知已经初始化完毕 sendNotification(MyAppFacade.APP_STARTUP_OVER,app); } } }
只有一个execute()函数,它的任务便是注册前面提到的两个Mediator和一个Proxy,用到的是registerProxy()与registerMediator()两个函数,完成注册后便可以对外Send MyAppFacade.APP_STARTUP_OVER 了。关注这一Notificator的便是前面已经建立映射的 GetUrlListCommand 。同样一个 GetUrlListCommand 会被实例化,再调用其execute()函数。
tip:Proxy类的构造函数需要一个proxyName:String作为其唯一标识,可以通过这一字符串得到该Proxy的引用,这里也建议使用字符常量
package MyApp.Controller { import MyApp.Model.ImageUrlListProxy; import org.puremvc.as3.interfaces.ICommand; import org.puremvc.as3.interfaces.INotification; import org.puremvc.as3.patterns.command.SimpleCommand; public class GetUrlListCommand extends SimpleCommand implements ICommand { public function GetUrlListCommand() { super(); } override public function execute(notification:INotification):void { //得到图片链接 (facade.retrieveProxy( ImageUrlListProxy.NAME ) as ImageUrlListProxy).loadUrlList(); } } }
好简单,呵呵,得到 ImageUrlListProxy 的实例,调用其loadUrlList()函数就可以了。前面提到Proxy不会去接收任何Notification,所以只能通过调用其成员函数的形式来使用它。
看看ImageUrlListProxy的代码:
package MyApp.Model { import MyApp.Model.VO.ImageUrlVO; import org.puremvc.as3.interfaces.IProxy; import org.puremvc.as3.patterns.proxy.Proxy; public class ImageUrlListProxy extends Proxy implements IProxy { public static const NAME:String = "ImageUrlListProxy"; //定义一些Notification字符常量 public static const URL_LOAD_COMPLETE:String = "url_load_complete"; public function ImageUrlListProxy(proxyName:String=null, data:Object=null) { super(proxyName,data); } public function loadUrlList():void{ data = new Array(); //push六张图片的Url data.push(new ImageUrlVO("http://www.mjbox.com/r/io/ioryioryzhan/pic1.jpg","卡莫")); data.push(new ImageUrlVO("http://www.mjbox.com/r/io/ioryioryzhan/pic2.jpg","李时珍")); data.push(new ImageUrlVO("http://www.mjbox.com/r/io/ioryioryzhan/pic3.jpg","姚明")); data.push(new ImageUrlVO("http://www.mjbox.com/r/io/ioryioryzhan/pic4.jpg","费得了")); data.push(new ImageUrlVO("http://www.mjbox.com/r/io/ioryioryzhan/pic5.jpg","伍兹")); data.push(new ImageUrlVO("http://www.mjbox.com/r/io/ioryioryzhan/pic6.jpg","不认得")); //通知image Url已经全部得到了 if(data==null)trace("data is null"); sendNotification( URL_LOAD_COMPLETE ,data ); } } }
loadUrlList()函数去得到图片信息,由于没有后台,所以只能用这种直接写硬编码的方式了, ,会有很多方式得到数据,如前面提到的HttpService及RemoteObject等。同步的异步的都可以用。
Proxy 有一个data成员,是个Object,用来盛放接收到的数据。得到数据后便可以Send一个Notification (URL_LOAD_COMPLETE)了。接下来看关注这个Notification的ImageMediator。
package MyApp.View { import mx.controls.Alert; import mx.controls.Image; import mx.controls.Label; import MyApp.Model.ImageUrlListProxy; import MyApp.Model.VO.ImageUrlVO; import org.puremvc.as3.interfaces.IMediator; import org.puremvc.as3.interfaces.INotification; import org.puremvc.as3.patterns.mediator.Mediator; public class ImageMediator extends Mediator implements IMediator { public static const NAME:String = "ImageMediator"; private var arrayOfImage:Array=null; private var currentIndex:int=-1; public function ImageMediator(mediatorName:String=null, viewComponent:Object=null) { super(mediatorName, viewComponent); } override public function listNotificationInterests():Array{ //列出感兴趣的Notification return [ ImageUrlListProxy.URL_LOAD_COMPLETE, ControlBtnsMediator.NEXT_IMAGE, ControlBtnsMediator.PREV_IMAGE ]; } override public function handleNotification(notification:INotification):void{ switch(notification.getName()){ case ImageUrlListProxy.URL_LOAD_COMPLETE: arrayOfImage = notification.getBody() as Array; if(arrayOfImage){ trace(arrayOfImage.length); trace((viewComponent.nameLabel as Label).text); (viewComponent.nameLabel as Label).text = (arrayOfImage[0] as ImageUrlVO).name; (viewComponent.image as Image).source = (arrayOfImage[0] as ImageUrlVO).url; currentIndex = 0; }else{ Alert.show("没有得到图片链接","错误"); } break; case ControlBtnsMediator.NEXT_IMAGE: if(currentIndex==-1)break; if(currentIndex >= arrayOfImage.length-1 ){Alert.show("已经是最后一张图片了","错误");} else{ trace((viewComponent.nameLabel as Label)); (viewComponent.nameLabel as Label).text = (arrayOfImage[currentIndex+1] as ImageUrlVO).name; (viewComponent.image as Image).source = (arrayOfImage[currentIndex+1] as ImageUrlVO).url; ++currentIndex; } break; case ControlBtnsMediator.PREV_IMAGE: if(currentIndex==-1)break; if(currentIndex ==0 ){Alert.show("目前是第一张图片","错误");} else{ (viewComponent.nameLabel as Label).text = (arrayOfImage[currentIndex+-1] as ImageUrlVO).name; (viewComponent.image as Image).source = (arrayOfImage[currentIndex-1] as ImageUrlVO).url; --currentIndex; } break; default:break; } } } }
ImageMediator除了关注ImageUrlListProxy.URL_LOAD_COMPLETE外,还要关注ControlBtnsMediator.NEXT_IMAGE以及ControlBtnsMediator.PREV_IMAGE,即为示下一张或上一张图片。
具体怎么将Mediator与其关注的Notification关联起来呢,listNotificationInterests(),就是它了。它要求返回一个字符数组,在注册这个Mediator时,该函数就会被调用,之后,当一个Notification被发送时,如果该Notification的字符串存在于这个字符数组时,这个Mediator就能接收到。
处理Notification是在handleNotification()函数内进行的,通过switch/case的方式,对不同的Notification进行不同的处理。会MFC的筒子们一定会觉得好熟悉啊,在 MFC 里,窗口函数也是这样来处理消息的。
具体代码就不分析了,很简单的。
最后就只有ControlBtnsMediator了。
package MyApp.View { import flash.events.MouseEvent; import mx.controls.Button; import org.puremvc.as3.interfaces.IMediator; import org.puremvc.as3.patterns.mediator.Mediator; public class ControlBtnsMediator extends Mediator implements IMediator { public static const NAME:String = "ControlBtnsMediator"; public static const NEXT_IMAGE:String = "next_image"; public static const PREV_IMAGE:String = "prev_image"; public function ControlBtnsMediator(mediatorName:String=null, viewComponent:Object=null) { super(mediatorName, viewComponent); (viewComponent.btnPrev as Button).addEventListener(MouseEvent.CLICK,onClickPrev); (viewComponent.btnNext as Button).addEventListener(MouseEvent.CLICK,onClickNext); } private function onClickPrev(e:MouseEvent):void{ sendNotification(PREV_IMAGE); } private function onClickNext(e:MouseEvent):void{ sendNotification(NEXT_IMAGE); } } }
注册监听,响应时发送相应的Notification。
好了,都介绍完了,点击运行吧。
附件中有一个pureMVC的中文文档,以及Project的源文件,pureMVC的代码Project的源文件中。
- pureMvc.rar (431.8 KB)
- 描述: pureMVC.pdf
- 下载次数: 4697
- HelloPureMVC.rar (338.9 KB)
- 描述: Project
- 下载次数: 5202
评论
最近看官方文档时,被Proxy这个家伙给难住了,因为官方文档的工程代码不全,搞得没办法写下去了。茫茫人海之中,看了作者的帖子,思路很清晰,口吻很细腻,看完之后,果然接解决问题了。
给作者提个建议:把ImageMediator中的handleNotification的处理方法,写到Proxy中,之后再新建一个command,它调用Proxy中的方法来处理。这样是不是更“纯”一些呢。呵呵。。
可能作者现在早已变成更牛的牛人,祝大家共同进步,事业有成!
这篇文章http://www.ibm.com/developerworks/cn/java/j-lo-puremvc/index.html
最近看官方文档时,被Proxy这个家伙给难住了,因为官方文档的工程代码不全,搞得没办法写下去了。茫茫人海之中,看了作者的帖子,思路很清晰,口吻很细腻,看完之后,果然接解决问题了。
给作者提个建议:把ImageMediator中的handleNotification的处理方法,写到Proxy中,之后再新建一个command,它调用Proxy中的方法来处理。这样是不是更“纯”一些呢。呵呵。。
可能作者现在早已变成更牛的牛人,祝大家共同进步,事业有成!
这篇文章中说的貌似也是将更新视图的处理逻辑放到了mediator里了。proxy只负责接收、存储数据。
最近看官方文档时,被Proxy这个家伙给难住了,因为官方文档的工程代码不全,搞得没办法写下去了。茫茫人海之中,看了作者的帖子,思路很清晰,口吻很细腻,看完之后,果然接解决问题了。
给作者提个建议:把ImageMediator中的handleNotification的处理方法,写到Proxy中,之后再新建一个command,它调用Proxy中的方法来处理。这样是不是更“纯”一些呢。呵呵。。
可能作者现在早已变成更牛的牛人,祝大家共同进步,事业有成!
呵呵,很久没来javaeye了,这次想过来发个招聘的,
很高兴我的博文能解决你的问题,
话说回来,上班以后,再也没用过这些框架了,
都是自己写些接口,自已mvc,虽说没有pureMVC这样牛,
但胜在,自己写的,呵呵
最近看官方文档时,被Proxy这个家伙给难住了,因为官方文档的工程代码不全,搞得没办法写下去了。茫茫人海之中,看了作者的帖子,思路很清晰,口吻很细腻,看完之后,果然接解决问题了。
给作者提个建议:把ImageMediator中的handleNotification的处理方法,写到Proxy中,之后再新建一个command,它调用Proxy中的方法来处理。这样是不是更“纯”一些呢。呵呵。。
可能作者现在早已变成更牛的牛人,祝大家共同进步,事业有成!
按下next button,去读下一个数据,从而view发生了改变,为什么在你的代码中还是在view的类里处理的呢? 总觉得mvc的模式中,事件发生后应该由controller通知model改变,在model改变然后再刷新view的啊
赞同你的说法,我也是刚刚看到这里,觉得很有问题,不只是上下一页,就连COMPLETE处理也应该在Command里面处理.楼主结构没搞好啊,但文章还是说得很好的
中是可以发的!
发表评论
-
mac 下 Flash Builder 4.7 破解
2013-01-14 15:44 9105项目 要做一个小东东,只好用Flex AIR来做, 已经找 ... -
flash as3中使用html中 <a>标签的一个有意思的问题
2011-12-08 17:37 1605<a href="#"> & ... -
雨中的播放器
2009-10-19 18:32 1599最近在网上看到一个用flash模拟下雨的例子,很好看,研究了它 ... -
JSON.decode() Unexpected ' encountered JSONTokenizer/parseError()错误分析
2009-08-22 02:19 4640啥也不说了,再次说明用别人的东西一定要小心,as3coreli ... -
flex 自定义TweenEffect方法
2009-06-15 13:39 3070rh 发现很久没有写BLOG了,罪过罪过,先忙着找工 ... -
得到控件的BitmapData位图信息,来做效果
2008-07-23 19:42 4411尝试得到控件的快照,就像位图信息,然后用来做效果。查查文档,真 ... -
一个图片展示效果:photoStack
2008-07-14 22:08 2405创意是网上的,有点画虎不成反类犬,哈哈 怎么用?不停地点照 ... -
flex中使用GoogleMap:添加Control
2008-07-05 23:22 3284在Flex中使用GoogleMap,可以让自己的网站有 ... -
flex htmlText中使用css的简单方法
2008-07-04 13:43 8974在设置控件htmlText属性时,经常要涉及到设定样式 ... -
在Flex中使用Json (1)
2008-06-26 10:39 8168要用到JSON,看了一 ... -
使用lcds时actionscript与java数据类型转换
2008-06-16 17:02 4483使用lcds时,由于直接可以和java打交道,可以不用 ... -
flex + tomcat + myEclipse环境 lcds的配置与使用
2008-06-14 20:30 61381.我的配置环境为: flexBuilder3,LCDS2 ...
相关推荐
PureMVC开发框架使用手册,PureMVC包含多个版本,这个文档是Flex版本 的MVC开发框架说明,
NULL 博文链接:https://wwwflex.iteye.com/blog/841899
flex PureMVC框架实例 flex PureMVC框架
pureMVC源码实例(flex的mvc框架)
PureMVC是一个定位于设计高性能RIA客户端的基于模式的框架。 本文在介绍PureMVC的同时,以在公司总结的实例源码(公司内部培训资料)讲解如何使用PureMVC进行FLEX开发,内涵大量注释,一读即懂
flex puremvc例子flex puremvc例子flex puremvc例子flex puremvc例子
Flex PureMVC页面跳转
开发环境flash builder 4,sdk:flex4.1,PureMVC 3.2.04,简单的demo,结构清晰,有必要的注释,工程导入flash builder即可。用户名/密码为:admin/admin视为验证通过。
flex框架 PureMVC_study
pureMVC框架 pureMVC源码 学习pureMVC的知识
As puremvc 实例,代码是flex4.6平台的,找了很多资料都是以前的代码用不起来,这个是新的,没怎么用自带的组件,初学者可以看看怎么回事。
介绍了PureMVC框架结构以及PureMVC下消息发送机制,有助于更好的了解和学习PureMVC架构
一个以pureMVC为flex前端框架,blazeds为通信服务器,spring和hibernate为服务端框架,实现了增删改等功能的完整实例,数据库使用mysql,部分关键地方加了注释,enjoy!
PureMVC教程,是学习PureMVC框架的好文章,PureMVC教程,是学习PureMVC框架的好文章,PureMVC教程,是学习PureMVC框架的好文章PureMVC教程,是学习PureMVC框架的好文章,PureMVC教程,是学习PureMVC框架的好文章,PureMVC...
puremvc 框架源码及教程, 附带一个使用示例 puremvc 框架源码及教程, 附带一个使用示例
这是一个使用C#开发语言的基于PureMVC框架的Web登录Demo,是网上绝无仅有的实例。 本文以初学者的视角,详细地介绍PureMVC在ASP.NET的应用。 PureMVC不仅仅是Flex的MVC框架哦,而且它非常的小巧,还等什么呢,快来...
PureMVC框架 PureMVC中文文档 PureMVC教程
Pure MVC是在基于模型、视图和控制器MVC模式建立的一个轻量级的应用框架,此资源是PureMVC standard 单线程开发框架.
NULL 博文链接:https://as3.iteye.com/blog/903252