了解PureMVC的开源框架

每月两次,我们重温从历史Activetuts整个我们的读者最喜爱的职位+。本教程是首次出版,2009年5月。

现在你可能会再次提出一个项目,需要大量的编码和/或与同事合作工作。说,框架往往是结构,语义和生产力的最佳选择,它是安全的。

了解一个框架,可以采取了很多时间,但一旦你高兴,你的知识,你可以从字面上代码在思想的速度。PureMVC是一个AS3的大框架,有些人可能会说这是一个有点难以得到你的头左右,但你做,你会很高兴。

从演示中,你可以看到,我们正在努力,是非常简单,但它足以让你了解PureMVC的作品如何。


在我们开始之前...

在我们开始之前,我想,以确保基地覆盖。这是一个教程中级到高级Actionscripters,但不要被吓倒,如果你既不是,有没有像现在开始学习时间!

  1. 这个例子使用Flex Builder建立。你可以到Adobe的网站下载自己的副本(60天免费试用!) 但是,它会在你选择的IDE愉快地工作,是否Flashdevelop中FDT,或良好OL“ 的TextMate
  2. 就像我已经说过了,本教程是为中级到高级Actionscripters,所以我要跳过世俗的部分,如设立您在您所选择的IDE,等项目...
  3. 这是值得注意的,下次你做你的业务,这是最好先打印的副本PureMVC的最佳实践这是相当沉重的,但你会很高兴你读它。

第1步:设置

明智的做法是抓住自己的一个项目。zip文件的副本内,你会看到本教程基本设置。火了您的IDE(我的是Flex Builder),并创建一个新项目。接下来的事情,你需要做的是设置Flex编译器,使用在“src”文件夹中的源路径,调试bin和“部署”释放的bin文件夹的文件夹中的“调试”。简单。

其次,我已经包含“src”文件夹内的两个额外的库:Greensock的TweenLite(“SRC / GS”)  puremvc (SRC /资产/深港西部通道“)。你会发现,我用一个PureMVC的图书馆,而不是源文件夹。深港西部通道,这是因为我喜欢使用SWC文件。确保这两个库设置为编译调试和最终部署时。以下是该项目的目标布局的截图。虽然你多欢迎导入项目,并通过它的文件的文件,我会告诉你如何编写每个文件,所以你最后一个项目类似的例子。


第2步:基本原理

PureMVC的概念可以使我们最好的回避,但一旦你得到了你的头周围裸露的基本面,你很快就会被到处乱飞,你的方式。PureMVC的结构意味着,通知被用来运行某些命令,无论他们是在模型,视图或控制器。这些通知包括名称和一个可选的身体。身体参数,允许你发送到一个控制器,然后把它传递给模型,然后返回相关数据的视图(如点击按钮)的数据。

本通知的概念是指,PureMVC的结构如何成立的源文件有一个非常明确的:

  • 代理 (模型)
    代理是一个简单的模型。一个模型,这些人可能不知道,是一类处理,如加载XML数据存储和检索所有数据交易。代理与调解员或命令,从来不听或处理的通知,他们只派出他们。这意味着,为了一个命令或调解得到了一些数据保持,数据将被传递回呼吁通过通知的身体或通过检索代理的实例,从门面。代理他们的数据存储在称为VO(值对象)的公共类。他们只是简单的类的公共变量,我们可以保持我们的数据检索和更新通过我们的代理。
  • 调解员和他们的意见 (观点)
    调解员是一个类,它代表认为。在你的应用程序,可能有几个意见,这些意见将被延长一个DisplayObject类(否则他们不会有意见)。调解员会增加您的看法,你的基地(“viewComponent”类,它是第一个参数是通过调解员),它也将处理所有传入和传出的通知有关这一观点。这意味着调解员负责通知您的应用程序,如果用户已触发视图中的事件(如按一下按钮)和以更新它还将负责从代理传递数据到视图。调解员听取和处理通知本身是能够注册到新的门面调解时,他们需要,而不是加载它们一次。
  • 命令 (控制器)
    一个命令仅仅是一个控制器。虽然它不听通知本身,它从外观到管道的通知。这意味着一个命令运行条件语句允许它来确定它收到该通知,下一步该怎么做。以及接收通知,命令,可以向他们发送了。他们还可以注册代理,调解员和更多的命令。

希望,应该给你一个puremvc是如何设置的简单理解。对于如何通知可以“飞”解决您的应用程序的可视化表示,检查PureMVC的概念图

你可以原谅,如果你认为这是非常艰巨的,但一旦你坐下来,规划出您的应用程序看起来像什么,你很快就会明白我们要去:

  1. 我们的基类会火起来的门面
  2. 门面“开始”命令,然后调用
  3. up命令开始将注册我们的代理和申请调解
  4. 然后代理将引用其值对象,并等待进一步的通知
  5. 将注册申请调解的进展,调解员
  6. 的进展,调解员会创建所取得的进展视图,然后发出通知加载数据
  7. 门面会收到此通知,并通过它的数据命令
  8. 数据命令,然后将过滤的通知,并告诉代理加载数据
  9. 代理将通知所取得的进展,认为它加载的数据(它将会显示),进步(将更新),当它完成(它会被隐藏),调解员会处理这一切
  10. 然后代理将发送申请调解处理的通知
  11. 申请调解,将注册的URL视图的地方,我们将创建用户点击的按钮
  12. 网址视图调解员将通过从代理数据的URL视图的URL视图,并添加到舞台
  13. 用户将按下一个按钮,这将可以通过调解处理,并通知将被发送到代理
  14. 然后代理服务器将再次加载数据,总是中继状态的进度来看
  15. 然后代理将再次发送申请调解处理的通知
  16. 调解员会再告诉应用程序的URL视图调解隐藏的URL视图,然后注册的图像视图
  17. 图像视图调解员将创建代理的数据图像视图

这听起来可能很复杂,但它只是一个制动您的应用程序的功能分解成小的位大小块的情况。


第三步:一切与门面开始

每当你与PureMVC的工作,你必须明白,始终编码与门面开始。门面是一个层,把PureMVC框架,MVC代码和基地的ActionScript文件,在这种情况下,煤矿被称为“App.as”。App.as在运行时,将做它的业务,是否设立舞台缩放,帧频和诸如此类的东西;当它准备的门面后,它会调用来启动应用程序。

让我们一起创造我们的基地ActionScript文件。使用您喜欢的IDE创建一个新文件,并将它命名为“App.as”内的“SRC”,并确保它扩展Sprite类的,像这样:

		package
		{
			import flash.display.Sprite;

			public class App extends Sprite
			{
				public function App()
				{

				}
			}
		}
	

第四步:设置基地

现在,我们已经创造了我们的基类,随意添加的东西,如设置宽度,高度,背景颜色等。您可能需要的任何资产,如字体或图像,这也是很方便的导入。一旦你满意你的基类,然后我们可以继续前进创造的门面。下面是一个预览我的基类:

		package
		{
			import flash.display.GradientType;
			import flash.display.Sprite;
			import flash.geom.Matrix;
			import flash.text.Font;

			[SWF( width='600', height='400', frameRate='30', backgroundColor='#000000' )]

			public class App extends Sprite
			{
				[Embed( systemFont='Arial', fontName='Arial', mimeType='application/x-font' )]
				private var arialFont:Class;

				public function App()
				{
					init();
				}

				private function init():void
				{
					var mat:Matrix = new Matrix();
					var bg:Sprite = new Sprite();

					mat.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI * .5 );

					bg.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, 0x000000 ], [ 1, 1 ], [ 0, 255 ], mat );
					bg.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
					bg.graphics.endFill();

					addChild( bg );

					Font.registerFont( arialFont );
				}
			}
		}
	

第5步:设置门面

在这一步,我们深入研究直到PureMVC的世界。像我在第2步说,门面是一个重要的层一起握着你的应用程序。创建一个新类称为“ApplicationFacade.as”内“SRC / COM / flashtuts的的”,确保它扩展了门面,实现IFacade。请注意,我们的门面并不因为它延长Facade类有一个构造。在我们的门面,我们将有3与第4个可选的功能。此外,我们将有2个公共常量。下面是我们将致力于让我们的门面类,看起来像什么:

		package com.flashtuts
		{
			import com.flashtuts.controller.*;
			import com.flashtuts.model.*;
			import com.flashtuts.view.*;
			import com.flashtuts.view.component.ImagesView;
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.IFacade;
			import org.puremvc.as3.patterns.facade.Facade;
			import org.puremvc.as3.patterns.observer.Notification;

			public class ApplicationFacade extends Facade implements IFacade
			{
				public static const NAME:String							= 'ApplicationFacade';

				public static const STARTUP:String						= NAME + 'StartUp';

				public static function getInstance():ApplicationFacade
				{
					return (instance ? instance : new ApplicationFacade()) as ApplicationFacade;
				}

				override protected function initializeController():void
				{
					super.initializeController();

					registerCommand( STARTUP, StartupCommand );

					registerCommand( URLsView.DATA_GET, DataCommand );
					registerCommand( ImagesView.DATA_GET, DataCommand );
				}

				public function startup(stage:Object):void
				{
					sendNotification( STARTUP, 	stage );
				}

				override public function sendNotification(notificationName:String, body:Object=null, type:String=null):void
				{
					trace( 'Sent ' + notificationName );

					notifyObservers( new Notification( notificationName, body, type ) );
				}
			}
		}

内PureMVC的事件或“通知”用我们的意见或控制器内进行路由数据和触发功能。因此,因为我们的门面将发送一个通知,告诉它启动的应用程序的命令,我们创建了一个独特的恒定,将由门面用来发送命令,并开始了功能,听命令:

		public static const NAME:String							= 'ApplicationFacade';

		public static const STARTUP:String						= NAME + 'StartUp';

虽然你并不需要有一个恒定的所谓的名称,它是一个好主意,始终建立在类通知常数,以保持独特的上述通知的,不太容易受到人为错误(如拼写错误)。

接下来我们就来我们所需的功能,“getInstance()方法”。这是门面的第一和最重要的功能,并允许我们的基类来检索的门面的一个实例,然后射击开始up命令(我们会得到):

		public static function getInstance():ApplicationFacade
		{
			return (instance ? instance : new ApplicationFacade()) as ApplicationFacade;
		}

现在我们就来通知我们的控制器控制路由的功能,或PureMVC的呼吁他们,命令:

		override protected function initializeController():void
		{
			super.initializeController();

			registerCommand( STARTUP, StartupCommand );

			registerCommand( URLsView.DATA_GET, DataCommand );
			registerCommand( ImagesView.DATA_GET, DataCommand );
		}
	

这是非常重要的保持“registerCommand(启动,StartupCommand),”不这样做,应用程序将无法启动。它的基本含义是,门面将通过一个名为“启动”命令称为“StartupCommand”的通知。正如你可以看到,我有两个。他们都指向名为“DataCommand”,同时通知另一个控制器是获取数据的请求。

现在,我们得到我们所需的功能,没有我们的门面“启动()”。这一切的根本是火一个被路由通过的的“registerCommand”处理“StartupCommand”的通知:

	

最后,最后但绝非最不重要的,我们有我们的最终功能。这是一个可选的功能,我想补充时,我与PureMVC的工作,因为它让我看到了什么事件被解雇,以及以何种顺序。简单的功能覆盖“sendNotification()”函数,你在PureMVC的使用发送通知。以及通知应用程序的观察员,跟踪事件给你看:

		override public function sendNotification(notificationName:String, body:Object=null, type:String=null):void
		{
			trace( 'Sent ' + notificationName );

			notifyObservers( new Notification( notificationName, body, type ) );
		}

所以这是我们的门面。我们完成之前,我们需要申请一个行到我们的基类。此行只会让我们的门面的一个实例,然后运行up命令开始:

		ApplicationFacade.getInstance().startup( this );
	

确保你把这个文件,无论你的基类是做年底。例如,我已经把所有的东西,我的应用程序,设置背景渐变下:

		package
		{
			import com.flashtuts.ApplicationFacade;

			import flash.display.GradientType;
			import flash.display.Sprite;
			import flash.geom.Matrix;
			import flash.text.Font;

			[SWF( width='600', height='400', frameRate='30', backgroundColor='#000000' )]

			public class App extends Sprite
			{
				[Embed( systemFont='Arial', fontName='Arial', mimeType='application/x-font' )]
				private var arialFont:Class;

				public function App()
				{
					init();
				}

				private function init():void
				{
					var mat:Matrix = new Matrix();
					var bg:Sprite = new Sprite();

					mat.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI * .5 );

					bg.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, 0x000000 ], [ 1, 1 ], [ 0, 255 ], mat );
					bg.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
					bg.graphics.endFill();

					addChild( bg );

					Font.registerFont( arialFont );

					ApplicationFacade.getInstance().startup( this );
				}
			}
		}
	

现在,我们已经准备好让我们的手脏。


步骤6: up命令开始

正如在第4步讨论,门面处理所有路由的命令(控制器)的通知。我们要创造的第一个命令是“StartupCommand”。因此,创建一个新的文件名为“StartupCommand.as”内“的src / COM / flashtuts的/控制器”。确保它延伸SimpleCommand实现ICommand。就像我们的门面,我们的命令将不会有构造函数,而不是覆盖从公众的SimpleCommand类“的execute()函数调用”:

		package com.flashtuts.controller
		{
			import com.flashtuts.model.DataProxy;
			import com.flashtuts.view.ApplicationMediator;

			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
			{
				override public function execute(notification:INotification):void
				{
					facade.registerProxy( new DataProxy() );

					facade.registerMediator( new ApplicationMediator( notification.getBody() as App ) );
				}
			}
		}

你会发现,在我们的“执行()”函数,还有一个被称为“通知”的说法。我们不需要使用,因为这个阶段,但是这将成为东西,我们不使用在我们的其他命令。作为使用此命令来启动我们的应用程序,首先它注册代理(模型):

		facade.registerProxy( new DataProxy() );
	

然后我们的调解员:

		facade.registerMediator( new ApplicationMediator( notification.getBody() as App ) );
	

所以,现在我们有我们的启动命令准备。我们要做的是创造我们的代理,然后到我们的ApplicationMediator。


第7步:创建一个代理

现在,我们有我们的“StartupCommand”注册我们的代理,我们需要确保代理的存在。因此,创建一个新的文件名为“DataProxy.as”内“SRC / COM / flashtuts的/模型”,并确保它延伸代理和实现IProxy。要开始与我们只是要在我们的代理有两个功能:构造和“获取”功能来检索的VO(值对象):

		package com.flashtuts.model
		{
			import com.flashtuts.model.vo.DataVO;

			import org.puremvc.as3.interfaces.IProxy;
			import org.puremvc.as3.patterns.proxy.Proxy;

			public class DataProxy extends Proxy implements IProxy
			{
				public static const NAME:String							= 'DataProxy';

				public function DataProxy()
				{
					super( NAME, new DataVO() );
				}

				public function get vo():DataVO
				{
					return data as DataVO;
				}
			}
		}

正如你可以看到,在我们代理的第一个功能是我们的构造,我们的“超级()”两个变量:代理的名称(由名称不变)和旁白。我们需要通过代理的名称,因为这将允许我们检索门面的实例,而不是创建一个新的实例,并失去我们的VO的数据:

		public static const NAME:String							= 'DataProxy';

		public function DataProxy()
		{
			super( NAME, new DataVO() );
		}
	

第二个功能是一个简单的get函数返回我们的旁白。这使得代理,命令和调解员可以方便地访问通过代理VO:

		public function get vo():DataVO
		{
			return data as DataVO;
		}
	

之前我们完成我们的代理,我们需要建立我们的旁白,所以称为“SRC / COM / flashtuts /模型/ VO”内“DataVO.as”创建一个新类。然后我们要添加三个公共变量:“dataURL:字符串”,的“urlsArray:阵列”和“urlsDataArray:阵列”。我们要去设置“dataURL的”指向“SRC /资产/ XML”被称为“data.xml中”和其他两个我们只是将它们设置为空数组的XML文件:

		package com.flashtuts.model.vo
		{
			public class DataVO
			{
				public var dataURL:String								= 'assets/xml/data.xml';
				public var urlsArray:Array								= [ ];
				public var urlsDataArray:Array							= [ ];
			}
		}
	

这些XML文件中的内容:

		<?xml version="1.0" encoding="UTF-8"?>
		<urls>
			<url>http://api.flickr.com/services/rest/?method=flickr.photos.search&amp;tags=london&amp;api_key=YOURAPIKEY</url>
			<url>http://api.flickr.com/services/rest/?method=flickr.photos.search&amp;tags=paris&amp;api_key=YOURAPIKEY</url>
			<url>http://api.flickr.com/services/rest/?method=flickr.photos.search&amp;tags=new%20york&amp;api_key=YOURAPIKEY</url>
		</urls>
	

注:你会看到,我删除了我的API密钥。你可以很容易地申请一个Flickr的API文档网站

现在,我们已经有了我们的代理和旁白到位,我们需要建立我们的调解员和意见。


第8步:创建ApplicationMediator

“ApplicationMediator”是坐在我们的的“StartupCommand”和你的看法调解员之间的层。作为您的应用程序变得越来越大,这将不再有意义注册您所有的调解员在一次(例如,在启动时)。因此,有一个父调停(的ApplicationMediator)的,可以听取围绕您的应用程序发送通知和注册的时候都需要调解。由于调解员代表的意见,视图所需的数据有时可能没有被载入尚未采取行动,因此,它似乎傻注册调解员不能够传递给它的任何数据,并创建视图。

首先,创建一个新文件称为“ApplicationMediator.as”“SRC / COM / flashtuts /视图”内,并确保它延伸调解和实现IMediator。下面是你应该瞄准“ApplicationMediator”的样子:

		package com.flashtuts.view
		{
			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class ApplicationMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'ApplicationMediator';

				public function ApplicationMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent );
				}
			}
		}

正如你可以看到,调解员开始与我们的老朋友“名称”的常数,它的构造。当我们注册在第6步的调解,我们通过一个阶段的实例,我们的基类(“App.as”)作为第一个参数。在我们的构造,超的名称和第一个参数,“viewComponent”,因为它是这将允许我们的调解,以增加他们的意见,在舞台上,我们的基类的viewComponent。

现在是一个好时机,开始谈论我们的意见。在我的例子中,我有三个:一个进度来看,一个URL选择视图和图像视图。对于每一个观点,我们有一名调解员。因为我们想要做的第一件事,是从我们的XML文件中加载的数据,似乎拟合来创建我们的进度来看,调解和然后注册“ApplicationMediator”的调解员。

通过扩展类中介,它可以让我们重写一个方便的功能,被称为“onRegister()”。当门面,注册了一个中介,这个函数被调用,因此,似乎最好的地方得到“ApplicationMediator”,注册为我们的进度来看调解:

		override public function onRegister():void
		{
			facade.registerMediator( new ProgressViewMediator( viewComponent ) );
		}
	

正如你可以看到,这是相同的风格,我们用在“StartupCommand”和我们传递“viewComponent”,调停,所以它能够在舞台上添加进度来看。您的应用程序调解员应该像这样:

		package com.flashtuts.view
		{
			import com.flashtuts.view.component.ProgressView;

			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class ApplicationMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'ApplicationMediator';

				public function ApplicationMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent );
				}

				override public function onRegister():void
				{
					facade.registerMediator( new ProgressViewMediator( viewComponent ) );
				}
			}
		}


第9步:
创建我们的进展调解和视图

现在,我们已经设置注册“ApplicationMediator”我们的的“ProgressViewMediator”,我们首先开始创建“ProgressView.as”类“的src / COM / flashtuts /视图/组件”内。这是一个类,简单的DisplayObject,在这种情况下,雪碧延伸。我不会去通过代码视图,因为它是任何Actionscripter相当标准,但我会谈谈的观点和下面的调停之间的相互作用:

		package com.flashtuts.view.component
		{
			import flash.display.Sprite;
			import flash.text.TextField;
			import flash.text.TextFieldAutoSize;
			import flash.text.TextFormat;

			import gs.TweenLite;

			public class ProgressView extends Sprite
			{
				public static const NAME:String							= 'ProgressView';

				public static const SHOW:String							= NAME + 'Show';
				public static const HIDE:String							= NAME + 'Hide';
				public static const UPDATE:String						= NAME + 'Update';

				private var textField:TextField;

				public function ProgressView()
				{
					init();
				}

				private function init():void
				{
					var textFormat:TextFormat = new TextFormat();

					textFormat.color = 0xFFFFFF;
					textFormat.font = 'Arial';

					textField = new TextField();

					textField.autoSize = TextFieldAutoSize.CENTER;
					textField.defaultTextFormat = textFormat;
					textField.embedFonts = true;
					textField.text = 'Please wait...';
					textField.x = 300 - ( textField.width / 2 );
					textField.y = 200 - ( textField.height / 2 );

					addChild( textField );
				}

				public function show():void
				{
					textField.text = 'Please wait...';

					TweenLite.to( this, .5, { autoAlpha: 1 } );
				}

				public function hide():void
				{
					TweenLite.to( this, .5, { autoAlpha: 0 } );
				}

				public function update(percent:Number):void
				{
					textField.text = 'Loaded ' + percent + '%';
				}
			}
		}

作为调停人“交谈”的观点,它是非常重要的观点和调解员可以将信息传递到另一个。调解员可以传递信息,作为调停人将在它宣布的一个实例,但认为将信息传递给我们依赖于事件的调停者(如用户点击一个按钮)(不混合与通知)。我们只是得到我们认为派遣一个事件,并得到我们的调解员听取该事件。因此,调解员可以处理该事件的观点,消化信息,并执行相应的东西。我们对这些事件的名称使用公共常量声明,因此我们认为有三个事件:显示隐藏更新(很像我们的门面)。

注:配售事件名称可以在门面(“ApplicationFacade.as”文件),或放置在相对 ​​的意见。我觉得它更容易和更清洁的保持在他们的意见,但它给你,你认为哪种方式工作更好地为您。

你可以告诉我创建了一个文本字段,将用于显示通过我们的应用程序加载的数据的百分比。

现在,我们可以移动的调解,所以称为“ProgressViewMediator.as”在“SRC / COM / flashtuts的中/视图”创建一个新文件,并确保它延伸调解,并实现IMediator。作为“ApplicationMediator”将遵循相同的风格,因此有一个构造函数有一个参数(“viewComponent”),公共常数,称为名称和重写“onRegister()”我们的朋友。下面是你的调解人应该像:

		package com.flashtuts.view
		{
			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class ProgressViewMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'ProgressViewMediator';

				public function ProgressViewMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent );
				}

				override public function onRegister():void
				{

				}
			}
		}
	


首先我们需要添加到我们作为一个引用到我们的中保:

		package com.flashtuts.view
		{
			import com.flashtuts.view.component.ProgressView;
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class ProgressViewMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'ProgressViewMediator';

				private var progressView:ProgressView;
				...
	


现在我们得到调解,所以我们必须添加到“viewComponent”我们认为:

		package com.flashtuts.view
		{
			import com.flashtuts.view.component.ProgressView;
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class ProgressViewMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'ProgressViewMediator';

				private var progressView:ProgressView;

				public function ProgressViewMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent );
				}

				override public function onRegister():void
				{
					progressView = new ProgressView();

					viewComponent.addChild( progressView );
				}
			}
		}
	


现在,我们已经有了我们的调解裸机,我们需要来看看我们的观点是打算做什么。好了,你大概可以告诉常量,我们认为是要告诉多少迄今已加载的用户,因此它具有公共常量显示隐藏更新因为这些都将是什么,我们认为会有什么反应(你可以告诉“秀()”,“隐藏()”和“更新()”在我们看来功能),我们需要我们的调解员来处理这些通知,并相应地执行这些功能。

我们将增加两个新的功能,我们的中保:“listNotificationInterests()”和“的handleNotification()”。第一个函数返回一个数组的所有调解员感兴趣(这就是为什么它如此重要,坚持在公共常量这些通知,使他们很容易参考)的通知。后者实际上与他们的东西。这种调解是唯一感兴趣的节目隐藏更新所以这是我们添加的第一个功能,并处理在第二

		package com.flashtuts.view
		{
			import com.flashtuts.view.component.ProgressView;
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class ProgressViewMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'ProgressViewMediator';

				private var progressView:ProgressView;

				public function ProgressViewMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent );
				}

				override public function onRegister():void
				{
					progressView = new ProgressView();

					viewComponent.addChild( progressView );

					sendNotification( URLsView.DATA_GET );
				}

				override public function listNotificationInterests():Array
				{
					return [
						ProgressView.SHOW,
						ProgressView.HIDE,
						ProgressView.UPDATE
					];
				}

				override public function handleNotification(notification:INotification):void
				{
					var name:String = notification.getName();
					var body:Object = notification.getBody();

					switch ( name )
					{
						case ProgressView.SHOW:
						progressView.show();

						break;

						case ProgressView.HIDE:
						progressView.hide();

						break;

						case ProgressView.UPDATE:
						progressView.update( body.percent );

						break;
					}
				}
			}
		}

你可以简单地看到,我们的handleNotification()“需要一个INotification的说法,一个类,它包含的名称机构的通知。我们用一个“开关”的语句,以确定该通知是要处理和运行相应的功能。简单。

恭喜!你已经达到第一个里程碑!我们不是来远吗?测试您的文件和你应该看到以下内容:


里程碑

到目前为止,我们已经创建了我们的门面,增加了一个命令,代理和应用程序的调解,然后创建一个视图,并把它添加到我们的应用程序使用视图的门面。


第10步:创建我们的网址查看

现在,我们要加载一些数据。之前,我们做到这一点,让我们的创建将用于显示此数据。正如我们正在装载三Flickr的API提要,我看到它恰当的,我们在我们的下一个视图创建三个按钮,允许用户点击,在这一点,我们的应用程序将返回相应的饲料图像。让我们再创建一个新的文件名为“URLsView.as”“SRC / COM / flashtuts的/视图/组件”,就像我们的“ProgressView”,这将扩展Sprite类:

		package com.flashtuts.view.component
		{
			import flash.display.Sprite;
			import flash.events.DataEvent;
			import flash.events.MouseEvent;
			import flash.text.TextField;
			import flash.text.TextFieldAutoSize;
			import flash.text.TextFormat;

			import gs.TweenLite;

			public class URLsView extends Sprite
			{
				public static const NAME:String							= 'URLsView';

				public static const DATA_GET:String						= NAME + 'DataGet';
				public static const DATA_READY:String					= NAME + 'DataReady';
				public static const SHOW:String							= NAME + 'Show';
				public static const HIDE:String							= NAME + 'Hide';
				public static const CLICKED:String						= NAME + 'Clicked';

				public function init(urls:Array):void
				{
					var i:Number = 0;
					var textFormat:TextFormat = new TextFormat();
					var textContainer:Sprite;
					var textField:TextField;

					textFormat.color = 0xFFFFFF;
					textFormat.font = 'Arial';

					for each ( var url:String in urls )
					{
						textContainer = new Sprite();

						textContainer.addEventListener( MouseEvent.CLICK, handleContainerClick );

						textContainer.buttonMode = true;
						textContainer.graphics.lineStyle( 1, 0xFFFFFF );
						textContainer.graphics.beginFill( 0x333333 );
						textContainer.graphics.drawRoundRect( 0, 0, 150, 30, 5, 5 );
						textContainer.graphics.endFill();
						textContainer.mouseChildren = false;
						textContainer.y = i * 40;

						textField = new TextField();

						textField.autoSize = TextFieldAutoSize.CENTER;
						textField.defaultTextFormat = textFormat;
						textField.embedFonts = true;
						textField.text = 'Select URL ' + ( ++i );
						textField.x = 75 - ( textField.width / 2 );
						textField.y = 15 - ( textField.height / 2 );

						textContainer.addChild( textField );

						addChild( textContainer );
					}

					alpha = 0;
					x = 300 - ( width / 2 );
					y = 200 - ( height / 2 );
				}

				public function show():void
				{
					TweenLite.to( this, .5, { autoAlpha: 1 } );
				}

				public function hide():void
				{
					TweenLite.to( this, .5, { autoAlpha: 0 } );
				}

				private function handleContainerClick(e:MouseEvent):void
				{
					var index:Number = getChildIndex( e.target as Sprite );

					dispatchEvent( new DataEvent( CLICKED, true, false, index.toString() ) );
				}
			}
		}
	


我不会走你所有的视图类,通 ​​过这个视图类。他们基本的AS3类,你应该熟悉它们。然而,你可以看到我已经离开的构造,我们只是想建立的按钮,当数据已被载入“DataProxy”。此外,在公共常量注意,主要DATA_GETDATA_READY的类的顶部这些都将被解雇,以信号,需要加载的数据,然后加载数据,并准备视图的事件。

我们现在就来我们的观点的调停,所以称为“URLsViewMediator.as”内“SRC / COM / flashtuts /视图”创建一个文件,并确保它延伸调解和实现IMediator。这就像在我们的应用程序之内的所有调解员。作为我们“ProgressViewMediator”这其中有一个构造,它超类的名称和“viewComponent”,也有重写“onRegister”功能。再次,就像“ProgressViewMediator”,我们宣布我们认为新的实例:

		package com.flashtuts.view
		{
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class URLsViewMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'URLsViewMediator';

				private var urlsView:URLsView;

				public function URLsViewMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent);
				}

				override public function onRegister():void
				{
					urlsView = new URLsView();
				}
			}
		}

现在,我们需要思考我们的观点是要干什么。那么,它允许用户点击一个按钮内,并派遣一个事件(这就是handleContainerClick的功能“()”内的观点确实)。我们要告诉我们的调解员,我们认为该事件侦听器,并进行相应的处理:

		package com.flashtuts.view
		{
			import com.flashtuts.view.component.URLsView;

			import flash.events.DataEvent;

			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class URLsViewMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'URLsViewMediator';

				private var urlsView:URLsView;

				public function URLsViewMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent);
				}

				override public function onRegister():void
				{
					urlsView = new URLsView();

					urlsView.addEventListener( URLsView.CLICKED, handleURLsViewClicked );
				}

				private function handleURLsViewClicked(e:DataEvent):void
				{

				}
			}
		}
	


现在,我们需要思考时,调解员将投入使用。记得刚才我说,有没有点运行调停之前,它需要吗?调解员不会被运行之前,我们需要它,所以我们假设它首次登记时,将数据的观点,以建立按钮的准备,所以我们更新我们的的“onRegister()”功能将数据发送到视图,显示视图,并把它添加到舞台。由于我们的数据存储在我们的“DataProxy”旁白,我们需要添加其他功能,这使我们能够访问门面的代理实例和检索数据从VO:

		override public function onRegister():void
		{
			urlsView = new URLsView();

			urlsView.addEventListener( URLsView.CLICKED, handleURLsViewClicked );

			urlsView.init( proxy.vo.urlsArray );

			urlsView.show();

			viewComponent.addChild( urlsView );
		}

		private function get proxy():DataProxy
		{
			return facade.retrieveProxy( DataProxy.NAME ) as DataProxy;
		}

最后,调解员将被创建时的数据的准备,我们需要告诉“ProgressView”我们不再想它是可见的,所以我们火称为“ProgressView.HIDE”,将捡到的通知“ ProgressViewMediator“,并会告诉的”ProgressView“隐藏自身:

		override public function onRegister():void
		{
			urlsView = new URLsView();

			urlsView.addEventListener( URLsView.CLICKED, handleURLsViewClicked );

			urlsView.init( proxy.vo.urlsArray );

			urlsView.show();

			viewComponent.addChild( urlsView );

			sendNotification( ProgressView.HIDE );
		}

再次,我们才可以继续下去,我们需要思考的有关通知调解员将要听的。既然我们要作出一个可用的应用程序,还有没有点,不要让用户返回并选择另一个Flickr的饲料URL,所以是有意义的,让这一观点被再次显示。这是其中的公共常量显示有玩(你会发现,我有一个命名约定,当它涉及到所有的通知,这是一件好事,会加快您的开发)。只是想与“ProgressViewMediator”,我们添加“listNotificationInterests的()”和“的handleNotification()”功能给我们的类:

		package com.flashtuts.view
		{
			import com.flashtuts.model.DataProxy;
			import com.flashtuts.view.component.ProgressView;
			import com.flashtuts.view.component.URLsView;

			import flash.events.DataEvent;

			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class URLsViewMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'URLsViewMediator';

				private var urlsView:URLsView;

				public function URLsViewMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent);
				}

				override public function onRegister():void
				{
					urlsView = new URLsView();

					urlsView.addEventListener( URLsView.CLICKED, handleURLsViewClicked );

					urlsView.init( proxy.vo.urlsArray );

					urlsView.show();

					viewComponent.addChild( urlsView );

					sendNotification( ProgressView.HIDE );
				}

				override public function listNotificationInterests():Array
				{
					return [
						URLsView.SHOW
					];
				}

				override public function handleNotification(notification:INotification):void
				{
					var name:String = notification.getName();
					var body:Object = notification.getBody();

					switch ( name )
					{
						case URLsView.SHOW:
						urlsView.show();

						break;
					}
				}

				private function handleURLsViewClicked(e:DataEvent):void
				{
					urlsView.hide();

					sendNotification( URLsView.CLICKED, { index: e.data } );
				}

				private function get proxy():DataProxy
				{
					return facade.retrieveProxy( DataProxy.NAME ) as DataProxy;
				}
			}
		}

你会发现,我已经添加了一些东西“handleContainerClick()”函数。这个函数是简单地传递事件名称“URLsView.CLICKED”按下按钮的索引(如0,1,2 ...)。我们会处理此事件不久,因为这是我们将使用它来加载用户回升Flickr的饲料事件。

现在,我们的看法是准备为我们的数据,我们可以进行代理,加载一些XML。呐喊呐喊!


第11步:载入数据

正如我上面提到,“ProgressViewMediator”触发了通知称为“URLsView.DATA_GET”。为了我们的代理收到此通知,我们必须要通过我们的门面,然后命令,然后调用代理的功能。首先,我们需要我们的门面内注册的命令,所以开辟“ApplicationFacade.as”,并添加了“registerCommand”功能的的“initializeController()”像这样的功能:

		package com.flashtuts
		{
			import com.flashtuts.controller.*;
			import com.flashtuts.model.*;
			import com.flashtuts.view.*;
			import com.flashtuts.view.component.ImagesView;
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.IFacade;
			import org.puremvc.as3.patterns.facade.Facade;
			import org.puremvc.as3.patterns.observer.Notification;

			public class ApplicationFacade extends Facade implements IFacade
			{
				public static const NAME:String							= 'ApplicationFacade';

				public static const STARTUP:String						= NAME + 'StartUp';

				public static function getInstance():ApplicationFacade
				{
					return (instance ? instance : new ApplicationFacade()) as ApplicationFacade;
				}

				override protected function initializeController():void
				{
					super.initializeController();

					registerCommand( STARTUP, StartupCommand );

					registerCommand( URLsView.DATA_GET, DataCommand );
				}

				public function startup(stage:Object):void
				{
					sendNotification( STARTUP, 	stage );
				}

				override public function sendNotification(notificationName:String, body:Object=null, type:String=null):void
				{
					trace( 'Sent ' + notificationName );

					notifyObservers( new Notification( notificationName, body, type ) );
				}
			}
		}
	


你会看到,我们告诉我们的门面,通过这个通知称为“DataCommand”命令,这是我们要来处理这个通知和运行代理控制器的名称。接下来,创建一个名为“DataCommand.as”中的“SRC / COM / flashtuts的/控制器”文件,它会需要,延长SimpleCommand实现ICommand的。我们班不会需要一个构造函数,因为我们有兴趣“的execute()”函数(就像“StartupCommand”):

		package com.flashtuts.controller
		{
			import org.puremvc.as3.interfaces.ICommand;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.command.SimpleCommand;

			public class DataCommand extends SimpleCommand implements ICommand
			{
				override public function execute(notification:INotification):void
				{

				}
			}
		}
	

如果你有一个锐利的眼睛,你会发现,我们正面临着我们的朋友INotification类。正如一名调解员,这个类为我们提供了通知的名字和身体,所以我们以同样的方式处理 - 开关:

		package com.flashtuts.controller
		{
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.ICommand;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.command.SimpleCommand;

			public class DataCommand extends SimpleCommand implements ICommand
			{
				override public function execute(notification:INotification):void
				{
					var name:String = notification.getName();
					var body:Object = notification.getBody();

					switch ( name )
					{
						case URLsView.DATA_GET:

						break;
					}
				}
			}
		}
	

因为我们希望该通知告诉代理加载一些数据,我们需要得到门面的代理实例,并得到它的火的功能。我们用同样的方法,我们在我们的调解,并创建一个get函数:

		package com.flashtuts.controller
		{
			import com.flashtuts.model.DataProxy;
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.ICommand;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.command.SimpleCommand;

			public class DataCommand extends SimpleCommand implements ICommand
			{
				override public function execute(notification:INotification):void
				{
					var name:String = notification.getName();
					var body:Object = notification.getBody();

					switch ( name )
					{
						case URLsView.DATA_GET:
						proxy.urlsDataGet();

						break;
					}
				}

				private function get proxy():DataProxy
				{
					return facade.retrieveProxy( DataProxy.NAME ) as DataProxy;
				}
			}
		}
	

最后,你会看到,我们调用一个函数内称为“urlsDataGet()”我们代理。这将载入我们的数据,所以我们最好创建它。开辟“DataProxy.as”,并创建一个名为“urlsDataGet()”,这将加载的数据,像这样的功能:

		package com.flashtuts.model
		{
			import com.flashtuts.model.vo.DataVO;
			import com.flashtuts.view.component.ProgressView;
			import com.flashtuts.view.component.URLsView;

			import flash.display.LoaderInfo;
			import flash.events.Event;
			import flash.events.ProgressEvent;
			import flash.net.URLLoader;
			import flash.net.URLRequest;
			import flash.utils.Dictionary;

			import org.puremvc.as3.interfaces.IProxy;
			import org.puremvc.as3.patterns.proxy.Proxy;

			public class DataProxy extends Proxy implements IProxy
			{
				public static const NAME:String							= 'DataProxy';

				private var indexDic:Dictionary = new Dictionary();

				public function DataProxy()
				{
					super( NAME, new DataVO() );
				}

				public function urlsDataGet():void
				{
					var request:URLRequest = new URLRequest();
					var loader:URLLoader = new URLLoader();

					sendNotification( ProgressView.SHOW );

					request.url = vo.dataURL;

					loader.addEventListener( ProgressEvent.PROGRESS, handleProgress );
					loader.addEventListener( Event.COMPLETE, handleURLsDataGetComplete );

					loader.load( request );
				}

				private function handleURLsDataGetComplete(e:Event):void
				{
					var data:XML = new XML( e.target.data );

					for each ( var url:XML in data..url )
					{
						vo.urlsArray.push( url.toString() );
						vo.urlsDataArray.push( '' );
					}

					sendNotification( URLsView.DATA_READY );
				}

				private function handleProgress(e:ProgressEvent):void
				{
					sendNotification( ProgressView.UPDATE, { percent: Math.round( ( e.bytesLoaded / e.bytesTotal ) * 100 ) } );
				}

				public function get vo():DataVO
				{
					return data as DataVO;
				}
			}
		}
	


你会发现,我们正在利用我们的旁白再次创造一个get函数,使我们可以使用,并添加到它的数据。您应该熟悉加载XML数据,所以我不会走,通过功能,你应该能够看到他们做什么。你也许会奇怪,为什么我运行通过的URL从XML数据的循环和填充一个空字符串数组,以后你会发现...

主要的事情,我会提到“handleProgress()”和“handleURLsDataGetComplete()”功能。他们都将通知发送到应用程序,首先发送一个数据加载的百分比我们的进度来看(还记得我说的通知是由一个名字和身体?),后者发送一个通知到应用程序的说明,我们的第一数据位已完成加载。

最后,因为我们只希望我们的“URLsViewMediator”和的“URLsView”要注册的数据准备好时,我们需要修改申请调解,调解时,该事件发送到注册:

		package com.flashtuts.view
		{
			import com.flashtuts.view.component.ProgressView;
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class ApplicationMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'ApplicationMediator';

				public function ApplicationMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent );
				}

				override public function onRegister():void
				{
					facade.registerMediator( new ProgressViewMediator( viewComponent ) );
				}

				override public function listNotificationInterests():Array
				{
					return [
						URLsView.DATA_READY
					];
				}

				override public function handleNotification(notification:INotification):void
				{
					var name:String = notification.getName();
					var body:Object = notification.getBody();

					switch ( name )
					{
						case URLsView.DATA_READY:
						facade.registerMediator( new URLsViewMediator( viewComponent ) );

						break;
					}
				}
			}
		}
	


代码应该不会太陌生,但你可以看到我们设置的通知,我们希望它来听,然后处理它们。在这种情况下,注册的“URLsViewMediator”运行其的“onRegister()”功能,并建立视图。

我们在未来的里程碑!现在,我们应该看到,我们的应用程序将加载XML数据,然后将此数据传递到我们的的“URLsViewMediator”,这将反过来告诉的“URLsView”创造一些准备为用户点击按钮:


里程碑

给自己拍拍背面为你已经取得了很多!现在,你应该熟悉通知如何发挥应用程序中的一个大的一部分,整个结构所带来的门面一起。下位将是一件轻而易举的...


第12步:处理用户事件

正如我刚才解释,有一种观点将调度用户事件,如鼠标移动,或在这种情况下,点击鼠标。此事件将被拾起其调停,然后决定做什么。由于我们已经设置了“URLsViewMediator”发送按钮的索引内的功能的“handleContainerClick()”,现在我们需要来处理这一事件和随后的数据加载。首先,我们需要建立我们的最终观点和调解。

这里的观点:

		package com.flashtuts.view.component
		{
			import flash.display.Loader;
			import flash.display.Sprite;
			import flash.events.Event;
			import flash.events.MouseEvent;
			import flash.net.URLRequest;
			import flash.text.TextField;
			import flash.text.TextFieldAutoSize;
			import flash.text.TextFormat;

			import gs.TweenLite;

			public class ImagesView extends Sprite
			{
				public static const NAME:String							= 'ImagesView';

				public static const DATA_GET:String						= NAME + 'DataGet';
				public static const DATA_READY:String					= NAME + 'DataReady';
				public static const SHOW:String							= NAME + 'Show';
				public static const HIDE:String							= NAME + 'Hide';
				public static const GO_BACK_CLICKED:String				= NAME + 'GoBackClicked';

				public function init(images:XML):void
				{
					var maxImages:Number = 15;
					var perRow:Number = 5;
					var xRowCount:Number = 0;
					var yRowCount:Number = 0;
					var element:XML;
					var request:URLRequest;
					var loader:Loader;

					for ( var i:Number = 0; i < maxImages; i++ )
					{
						element = images..photo[ i ];

						request = new URLRequest();

						request.url = 'http://farm' + element.@farm + '.static.flickr.com/' + element.@server + '/' + element.@id + '_' +element.@secret + '_t.jpg';

						loader = new Loader();	

						if ( xRowCount == perRow )
						{
							xRowCount = 0;
							yRowCount++;
						}

						loader.contentLoaderInfo.addEventListener( Event.COMPLETE, handleLoaderComplete );

						loader.alpha = 1;
						loader.x = xRowCount * 120;
						loader.y = yRowCount * 120;

						loader.load( request );

						xRowCount++;

						addChild( loader );
					}

					addBackButton();

					alpha = 0;
				}

				private function handleLoaderComplete(e:Event):void
				{
					TweenLite.from( e.target.content, .5, { autoAlpha: 0 } );
				}

				private function addBackButton():void
				{
					var textFormat:TextFormat = new TextFormat();
					var textContainer:Sprite = new Sprite();
					var textField:TextField = new TextField();

					textFormat.color = 0xFFFFFF;
					textFormat.font = 'Arial';

					textContainer.addEventListener( MouseEvent.CLICK, handleContainerClick );

					textContainer.buttonMode = true;
					textContainer.graphics.lineStyle( 1, 0xFFFFFF );
					textContainer.graphics.beginFill( 0x333333 );
					textContainer.graphics.drawRoundRect( 0, 0, 150, 30, 5, 5 );
					textContainer.graphics.endFill();
					textContainer.mouseChildren = false;
					textContainer.x = 430;
					textContainer.y = 350;

					textField.autoSize = TextFieldAutoSize.CENTER;
					textField.defaultTextFormat = textFormat;
					textField.embedFonts = true;
					textField.text = 'Go back';
					textField.x = 75 - ( textField.width / 2 );
					textField.y = 15 - ( textField.height / 2 );

					textContainer.addChild( textField );

					addChild( textContainer );
				}

				private function handleContainerClick(e:MouseEvent=null):void
				{
					if ( numChildren > 0 )
					{
						for ( var i:Number = 0; i < numChildren; i++ )
						{
							removeChildAt( i );
						}

						handleContainerClick();
					}
					else
					{
						dispatchEvent( new Event( GO_BACK_CLICKED, true ) );
					}
				}

				public function show():void
				{
					TweenLite.to( this, .5, { autoAlpha: 1 } );
				}

				public function hide():void
				{
					TweenLite.to( this, .5, { autoAlpha: 0 } );
				}
			}
		}

有鉴于此确实是从Flickr API加载XML数据,建立一个图像的网格和后退按钮。这里的调解:

		package com.flashtuts.view
		{
			import com.flashtuts.model.DataProxy;
			import com.flashtuts.view.component.ImagesView;
			import com.flashtuts.view.component.ProgressView;
			import com.flashtuts.view.component.URLsView;

			import flash.events.Event;

			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class ImagesViewMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'ImagesViewMediator';

				private var imagesView:ImagesView;

				public function ImagesViewMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent );
				}

				override public function onRegister():void
				{
					imagesView = new ImagesView();

					imagesView.addEventListener( ImagesView.GO_BACK_CLICKED, handleImagesViewGoBackClicked );

					viewComponent.addChild( imagesView );
				}

				override public function listNotificationInterests():Array
				{
					return [
						ImagesView.DATA_READY
					];
				}

				override public function handleNotification(notification:INotification):void
				{
					var name:String = notification.getName();
					var body:Object = notification.getBody();

					switch ( name )
					{
						case ImagesView.DATA_READY:
						imagesView.init( proxy.vo.urlsDataArray[ body.index ] );

						imagesView.show();

						sendNotification( ProgressView.HIDE );

						break;
					}
				}

				private function handleImagesViewGoBackClicked(e:Event):void
				{
					imagesView.hide();

					sendNotification( URLsView.SHOW );
				}

				private function get proxy():DataProxy
				{
					return facade.retrieveProxy( DataProxy.NAME ) as DataProxy;
				}
			}
		}

再次,这一切都不应该是新的给你,因为我们只是简单地创建一个我们认为的实例,将它添加到舞台上,听众加入到我们认为(和他们的处理程序),然后通知其要听将如何处理他们。

为了处理此通知后,我们更新的应用程序调解最后一次设置它来听到的“URLsView.CLICKED的”通知:

		package com.flashtuts.view
		{
			import com.flashtuts.view.component.ImagesView;
			import com.flashtuts.view.component.ProgressView;
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.IMediator;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.mediator.Mediator;

			public class ApplicationMediator extends Mediator implements IMediator
			{
				public static const NAME:String							= 'ApplicationMediator';

				public function ApplicationMediator(viewComponent:Object=null)
				{
					super( NAME, viewComponent );
				}

				override public function onRegister():void
				{
					facade.registerMediator( new ProgressViewMediator( viewComponent ) );
				}

				override public function listNotificationInterests():Array
				{
					return [
						URLsView.DATA_READY,
						URLsView.CLICKED
					];
				}

				override public function handleNotification(notification:INotification):void
				{
					var name:String = notification.getName();
					var body:Object = notification.getBody();

					switch ( name )
					{
						case URLsView.DATA_READY:
						facade.registerMediator( new URLsViewMediator( viewComponent ) );

						break;

						case URLsView.CLICKED:
						if ( !facade.hasMediator( ImagesViewMediator.NAME ) )
						{
							facade.registerMediator( new ImagesViewMediator( viewComponent ) );
						}

						sendNotification( ImagesView.DATA_GET, body );				

						break;
					}
				}
			}
		}
	


有关此事件的处理有一点要注意:代码做的第一件事是检查已注册调解员。如果没有,它注册了,每个人都用它得到。这样做的原因,而不是重新注册,这是我们要为用户创建一个后退按钮能够回去接另一个Flickr的饲料。因为我们只需要显示和隐藏的按钮,让用户选择,没有必要重建。然而,由于用户将可能选择另一个Flickr的饲料,我们需要重建我们的形象。为了节省复制我们的代码,我们只建立图像时“ImagesViewMediator”已收到事件“ImagesView.DATA_READY”。

由于我们的应用程序发送“ImagesView.DATA_GET”,只要用户选择一个Flickr API,我们需要一个调整“ApplicationFacade”,“DataCommand”和“DataProxy”)处理事件和B)加载数据和发送事件。

我们首先编辑的“ApplicationFacade”增加了“registerCommand()”“initializeController()”函数:

 

然后我们告诉“DataCommand”如何处理它(通过代理):

		package com.flashtuts.controller
		{
			import com.flashtuts.model.DataProxy;
			import com.flashtuts.view.component.ImagesView;
			import com.flashtuts.view.component.URLsView;

			import org.puremvc.as3.interfaces.ICommand;
			import org.puremvc.as3.interfaces.INotification;
			import org.puremvc.as3.patterns.command.SimpleCommand;

			public class DataCommand extends SimpleCommand implements ICommand
			{
				override public function execute(notification:INotification):void
				{
					var name:String = notification.getName();
					var body:Object = notification.getBody();

					switch ( name )
					{
						case URLsView.DATA_GET:
						proxy.urlsDataGet();

						break;

						case ImagesView.DATA_GET:
						proxy.imagesDataGet( body.index );

						break;
					}
				}

				private function get proxy():DataProxy
				{
					return facade.retrieveProxy( DataProxy.NAME ) as DataProxy;
				}
			}
		}
	

最后,我们编辑“DataProxy”:

		package com.flashtuts.model
		{
			import com.flashtuts.model.vo.DataVO;
			import com.flashtuts.view.component.ImagesView;
			import com.flashtuts.view.component.ProgressView;
			import com.flashtuts.view.component.URLsView;

			import flash.display.LoaderInfo;
			import flash.events.Event;
			import flash.events.ProgressEvent;
			import flash.net.URLLoader;
			import flash.net.URLRequest;
			import flash.utils.Dictionary;

			import org.puremvc.as3.interfaces.IProxy;
			import org.puremvc.as3.patterns.proxy.Proxy;

			public class DataProxy extends Proxy implements IProxy
			{
				public static const NAME:String							= 'DataProxy';

				private var indexDic:Dictionary = new Dictionary();

				public function DataProxy()
				{
					super( NAME, new DataVO() );
				}

				public function urlsDataGet():void
				{
					var request:URLRequest = new URLRequest();
					var loader:URLLoader = new URLLoader();

					sendNotification( ProgressView.SHOW );

					request.url = vo.dataURL;

					loader.addEventListener( ProgressEvent.PROGRESS, handleProgress );
					loader.addEventListener( Event.COMPLETE, handleURLsDataGetComplete );

					loader.load( request );
				}

				private function handleURLsDataGetComplete(e:Event):void
				{
					var data:XML = new XML( e.target.data );

					for each ( var url:XML in data..url )
					{
						vo.urlsArray.push( url.toString() );
						vo.urlsDataArray.push( '' );
					}

					sendNotification( URLsView.DATA_READY );
				}

				public function imagesDataGet(index:Number):void
				{
					var request:URLRequest = new URLRequest();
					var loader:URLLoader = new URLLoader();

					sendNotification( ProgressView.SHOW );

					if ( vo.urlsDataArray[ index ] == '' )
					{
						request.url = vo.urlsArray[ index ];

						indexDic[ loader ] = index;

						loader.addEventListener( ProgressEvent.PROGRESS, handleProgress );
						loader.addEventListener( Event.COMPLETE, handleImagesDataGetComplete );

						loader.load( request );
					}
					else
					{
						handleImagesDataGetFinished( index );
					}
				}

				private function handleImagesDataGetComplete(e:Event):void
				{
					var data:XML = new XML( e.target.data );

					vo.urlsDataArray[ indexDic[ e.target ] ] = data;

					handleImagesDataGetFinished( indexDic[ e.target ] );
				}

				private function handleImagesDataGetFinished(index:Number):void
				{
					sendNotification( ImagesView.DATA_READY, { index: index } );
				}

				private function handleProgress(e:ProgressEvent):void
				{
					sendNotification( ProgressView.UPDATE, { percent: Math.round( ( e.bytesLoaded / e.bytesTotal ) * 100 ) } );
				}

				public function get vo():DataVO
				{
					return data as DataVO;
				}
			}
		}
	

你会注意到,我在“imagesDataGet()”函数执行的ActionScript巫术位。再次,它只是加载一些XML,没什么特别,但它只会加载一次独特的数据。这是有VOS和使用索引按钮被按下时的美丽。本质上发生什么情况是,如果用户按下按钮2(第三),它会检查,看看是否该指数绑定到它的任何资料(网址被首次加载时创建一个空字符串数组的循环)。如果有,就没有必要再加载数据,否则数据的加载和使用的美容字典,我们可以放入数组。

最后,这个代理,然后推的通知“ImagesView.DATA_READY的”回我们的应用程序,我们认为会发生一些神奇的......


你已经做到了!

还有你的第一个PureMVC的应用程序!你应该知道有一个PureMVC的作品如何理解和最有价值的是,一具骷髅,所以当它来开发更多的应用程序,你可以利用这个代码,返工,或只是用它作为参考。


脚注

PureMVC是一个伟大的工具,我用它在许多项目,但之间使用ActionScript 3.0和MXML中有一些关键的差别。当你使用MXML,您可以添加使用XML,像这样的意见:

		<?xml version="1.0" encoding="utf-8"?>
		<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%" height="100%" backgroundColor="#000000" backgroundAlpha=".6"
			creationComplete="ApplicationFacade.getInstance().startup( NAME, this )"
			xmlns:component="com.application.view.component.*">

			<mx:Script>
				<![CDATA[

					import com.application.ApplicationFacade;

					public static const NAME:String						= 'Showcase';

					public static const STACK_PROGRESS:Number			= 0;
					public static const STACK_MAIN:Number				= 1;

				]]>
			</mx:Script>

			<mx:Style source="Showcase.css" />

			<mx:ViewStack id="stack" width="980" height="750" horizontalCenter="0" verticalCenter="0" creationPolicy="all">
				<component:ProgressView id="progress" />
				<component:ShowcaseMainView id="main" />

			</mx:ViewStack>

		</mx:Application>
	

Flex会自动创建这些意见,而不是让你推迟他们的创作。因此,当你准备深入到更多的PureMVC的,他们已经创建了一个小的应用程序,它告诉你如何使用延迟的实例

我希望你喜欢本教程后,觉得自由离开任何疑问或反馈的意见!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值