配置与开始

将Starling项目配置为StarlingMVC项目,仅需几行代码。在继承于starling.display.Sprite的起始类里,创建一个StarlingMVC的实例,并传递给它三个参数:Starling显示对象的根对象(起始类的实例)、StarlingMVCConfig的实例,以及一些Beans(数组或BeanProvider)。

package com.mygame.views
{
import com.creativebottle.starlingmvc.StarlingMVC;
import com.creativebottle.starlingmvc.config.StarlingMVCConfig;
import com.creativebottle.starlingmvc.views.ViewManager;
import com.mygame.models.GameModel; import starling.core.Starling;
import starling.display.Sprite; public class GameMain extends Sprite
{
private var starlingMVC:StarlingMVC; public function GameMain()
{
var config:StarlingMVCConfig = new StarlingMVCConfig();
config.eventPackages = ["com.mygame.events"];
config.viewPackages = ["com.mygame.views"]; var beans:Array = [new GameModel(), new ViewManager(this)]; starlingMVC = new StarlingMVC(this, config, beans);
}
}
}

StarlingMVCConfig的实例告诉StarlingMVC它应该处理的事件包及视图包的位置。Beans数组仅仅是一组对象集合,可以包括任何类型的对象,框架会区别待之。(译者注:框架仅处理在视图包下的view对象的[ViewRemoved]标签,在处理[EventHandler]标签时,也仅处理事件包下的事件类型。)

在Flash Builder上的额外设置

使用Flash builder编译产品,AS编译器会严格剥离非标准的Metadata标签,除非另有指定。StarlingMVC的自定义标签对于实现强大的自动依赖注入特征是必须的,如果没有这些标签,StarlingMVC将毫无作用。

使编译器充许StarlingMVC的自定义标签非常简介,仅需在项目上添加几行额外的编译参数即可。

为添加编译参数,右键单击项目,选择”Properties“,然后选择”ActionScript Compiler“,在“Additional compiler arguments”后面追加:

-keep-as3-metadata+=Dispatcher
-keep-as3-metadata+=EventHandler
-keep-as3-metadata+=Inject
-keep-as3-metadata+=Juggler
-keep-as3-metadata+=PostConstruct
-keep-as3-metadata+=ViewAdded
-keep-as3-metadata+=ViewRemoved

这样StarlingMVC便可以工作了。

Beans

一个Bean是一个提供给StarlingMVC管理的一个对象的实例。Bean们可以被注入,接收注入,还有接收事件等。在StarlingMVC的配置阶段,有多种方式可以设置Bean元素:

对象实例

var beans:Array = [new GameModel(), new ViewManager(this)];

Bean实例

var beans:Array = [new Bean(new GameModel()), new Bean(new ViewManager(this))];

以上提供Bean实例的设置方法相比之下并无高明之处,但是Bean的构造器的第二个参数可以传递一个id。只有提供了id,在依赖注入时才可以使用。另外,如果没有提供id,Bean将以class type作key在框架中存储,如果你有两个类型相同的Bean,必须提供id,否则后者将覆盖前者。例:

var beans:Array = [new Bean(new GameModel(),"gameModelEasy"),new Bean(new GameModel(),"gameModelHard"), new ViewManager(this)];

BeanProvider实例

BeanProvider是Bean的集合,与简单的Bean数组相同,在BeanProvider内的bean,可以是任何类型,包括BeanProvider。

package com.mygame.config
{
import com.creativebottle.starlingmvc.beans.BeanProvider;
import com.mygame.assets.AssetModel;
import com.mygame.models.AudioModel;
import com.mygame.models.GameModel; public class Models extends BeanProvider
{
public function Models()
{
beans = [new GameModel(), new Bean(new AudioModel(),"audioModel"), new AssetModel()];
}
}
}

有了BeanProvider,便可以把它作为元素之一以数组的方式提供bean:

var beans:Array = [new Models(), new ViewManager(this)];

ProtoBeans

ProtoBean是在被注入才会被创建的Bean。一般的Bean要求提供一个类实例,ProtoBean要求提供一个类定义及一个id。

var beans:Array = [new ProtoBean(Character,"character"), new ViewManager(this)];

这里使用ProtoBean将充许StarlingMVC为你创建类的实例。它每一次被注入,均会实例化一个新的类的实例,在这种情况下,使用”Character”类而不是像一般的Bean那样使用一个单例。让StarlingMVC框架去创建一个类的实例,而不是使用”new Character()”创建的好处在于,前者可以被注入、监管事件等处理所有依赖注入事务。

依赖注入

依赖注入发生在所有Bean及所有Starling对象上。在公开属性或gettter/setter标以[Inject]无数据标签便是一个依赖项。一个注入可以这样定义:

package com.mygame.controllers
{
public class GameController
{
[Inject]
public var gameModel:GameModel; public function GameController():void
{ }
}
}

或者以id注入,如果id在指定Bean时已经提供了的话:

package com.mygame.controllers
{
public class GameController
{
[Inject(source="gameModel")]
public var gameModel:GameModel; public function GameController():void
{ }
}
}

在上面的例子中,如果GameModel是一个普通的Bean,框架会以在配置时创建的单例赋值它。如果它是一个Protobean,框架会创建一个实例再注入到变量中。

StarlingMVC同样支持注入Bean的属性。为了使用这个功能,源Bean必须有一个id(在配置时使用new Bean指定的id)。注入Bean的属性,在[Inject]内bean id加上“.”+属性的名称即可:

package com.mygame.controllers
{
public class GameController
{
[Inject(source="gameModel")]
public var gameModel:GameModel; [Inject(source="userModel.currentUser")]
public var currentUser:User; public function GameController():void
{ }
}
}

在上面的例子中,userModel的属性currentUser将会注入到我们的控制器的currentUser属性上。这个功能还支持递归,如果你想注入currentUser的firstName属性,你可以这样做:

[Inject(source="userModel.currentUser.firstName")]

.

绑定

注入操作同样支持简单的绑定机制,当源对象发生变化时,被注入的属性将会被自动更新。

package com.mygame.controllers
{
public class GameController
{
[Inject(source="gameModel")]
public var gameModel:GameModel; [Inject(source="userModel.currentUser", bind="true")]
public var currentUser:User; public function GameController():void
{ }
}
}

如上所示,在[Inject]标签中使用一个bind=”true”的参数实现绑定。userModel的currentUser属性变化之时,StarlingMVC将自动更新所有使用绑定的注入。此招同样适用于getter/setters方法,运用此法可使代码轻而易举地的实现属性的变化。

package com.mygame.controllers
{
public class GameController
{
[Inject(source="gameModel")]
public var gameModel:GameModel; [Inject(source="userModel.currentUser", bind="true")]
public function set currentUser(value:User):void
{
_currentUser = value; // Do something to update your UI with the new value
} public function get currentUser():User
{
return _currentUser;
}
private var _currentUser:User; public function GameController():void
{ }
}
}

绑定与Starling juggler相连,这意味着它会在每次advanceTime()方法被调用的时候自动检查绑定的属性的变化。这不同于Flex提供的即时绑定。绑定应该谨慎使用,因为检查绑定的属性变化是一个不小的开销。

做为自动绑定属性的另外一种选择,StarlingMVC支持通过使之失效的方式绑定。这个方法相对于自动绑定十分有效,因为在当属性更新时它给了你更多的控制。这个功能可以通过一个被注入的Bindings类例和一个”auto”参数实现:

package com.mygame.controllers
{
public class GameController
{
[Inject(source="gameModel")]
public var gameModel:GameModel; [Inject(source="userModel.currentUser", bind="true", auto="false")]
public function set currentUser(value:User):void
{
_currentUser = value; // Do something to update your UI with the new value
} public function get currentUser():User
{
return _currentUser;
}
private var _currentUser:User; public function GameController():void
{ }
}
} package com.mygame.models
{
public class UserModel
{
[Bindings]
public var bindings:Bindings; public function set currentUser(value:User):void
{
if(value != _currentUser)
{
_currentUser = value; bindings.invalidate(this, "currentUser");
}
} public function get currentUser():User
{
return _currentUser;
}
private var _currentUser:User;
}
}

事件

派发事件

StarlingMVC的事件通过两种渠道派发:1)StarlingMVC包含一个全局的starling.events.EventDispatcher的实例,派发事件的一个快速方法便是使用这个dispatcher。该dispatcher可以通过[Dispatcher]元数据标签被注入到任何一个Bean内。 2)显示对象可以使用自有的dispatchEvent()方法派发事件。该方法仅当事件bubble设置为true时有效。

处理事件

事件处理被指示为在bean的公开方法上添加[EventHandler(event="")]元数据标签。标签内事件的参数有两种写法:一为事件类型字符串

package com.mygame.controllers
{
public class GameController
{
[EventHandler(event="scoreChanged")]
public function scoreChanged(event:ScoreEvent):void
{ }
}
}

另一个为事件定义字符串:

package com.mygame.controllers
{
public class GameController
{
[EventHandler(event="ScoreEvent.SCORE_CHANGED")]
public function scoreChanged(event:ScoreEvent):void
{ }
}
}

使用第二种方式的好处,在于StarlingMVC会在事件初始化时检查事件类型是否真实存在,如果不存在,将抛出异常。另外还可以防止错误字。(译者注:这是StarlingMVC要求开发者提供的eventsPackage的原因。)

在上述两个例子中,处理函数必须接受一个派发的事件并处理。然而,[EventHandler]标签的第二个参数充许你指定事件的哪些属性将被传递给事件处理函数。例如:

package com.mygame.controllers
{
public class GameController
{
[EventHandler(event="ScoreEvent.SCORE_CHANGED", properties="user, newScore")]
public function scoreChanged(user:User, newScore:int):void
{ }
}
}

如上所示,StarlingMVC没有传递一个event整体给事件函数,而只是传递事件的”user” 与 “newScore”属性。注意:类型必须匹配,否则将会报错。

视图中间件

视图中间件是保持你的视图类与控制它们的代码分离的一种好方法。视图中间件的设定与其它Bean一样。使用[ViewAdded]元数据标签将一个视图链接到一个视图中间件之上。当视图被添加进显示列表之后,StarlingMVC将会检查所有标以[ViewAdded]标签的方法,如果被标识的方法的view参数的类型与被添加进显示列表的视图类型相同,显示对象将被传递进方法。同理,[ViewRemoved]标签用于当视图被从显示列表移除时所要执行的函数的注入。

package com.mygame.mediators
{
public class GameMediator
{
private var view:Game; [ViewAdded]
public function viewAdded(view:Game):void
{
this.view = view;
} [ViewRemoved]
public function viewRemoved(view:Game):void
{
this.view = null;
}
}
}

Bean的生命周期

一般情况下,bean被设置了初始化。但是,在bean被创建之后,依赖注入与事件监听并没有立即可用。为了在当bean完成注入时得到一个通知,我们可以在一个公开方法上添加[PostConstruct]标签,这个方法会在注入完成后被自动调用。同样的,当一个bean被销毁时,我们可以在一个公开方法上标以[PreDestroy]标签。该功能在所有标准bean及显示对象上可用。

package com.mygame.controllers
{
public class GameController
{
[Inject]
public var gameModel:GameModel; [PostConstruct]
public function postConstruct():void
{
// set up code here
} [PreDestroy]
public function preDestroy():void
{
// tear down code here
} [EventHandler(event="ScoreEvent.SCORE_CHANGED", properties="user, newScore")]
public function scoreChanged(user:User, newScore:int):void
{ }
}
} package com.mygame.controllers
{
public class GameModel
{
[Bindings]
public var bindings:Bindings; public function set score(value:int):void
{
if(value != _score)
{
_score = value; bindings.invalidate(this, "score");
}
} public function get score():int
{
return _score;
}
private var _score:int;
}
}

手动添加、移除Bean

手动添加、移除bean是通过事件完成的,派发BeanEvent.ADD_BEAN事件用于添加、处理一个新的bean,派发BeanEvent.REMOVE_BEAN事件将bean从系统移除。

package com.mygame.view
{
public class Game
{
public var gamePresentationModel:GamePresentationModel; [PostConstruct]
public function postConstruct():void
{
gamePresentationModel = new GamePresentationModel(); dispatchEvent(new BeanEvent(BeanEvent.ADD_BEAN, gamePresentationModel));
} [PreDestroy]
public function preDestroy():void
{
dispatchEvent(new BeanEvent(BeanEvent.REMOVE_BEAN, gamePresentationModel)); gamePresentationModel = null;
}
}
}

所上所示,我们为视图创建一个Model并且作为一个bean添加进StarlingMVC。Model将被作为一个bean处理,并马上获得注入与事件处理的优势。

Command模式

StarlingMVC包括对Command模式的支持。Command本质上是事件派发,执行,销毁时被创建的Bean。向框架添加command,需要在bean里添加Command类定义。

package com.mygame.views
{
import com.creativebottle.starlingmvc.StarlingMVC;
import com.creativebottle.starlingmvc.config.StarlingMVCConfig;
import com.creativebottle.starlingmvc.views.ViewManager;
import com.mygame.models.GameModel; import starling.core.Starling;
import starling.display.Sprite; public class GameMain extends Sprite
{
private var starlingMVC:StarlingMVC; public function GameMain()
{
var config:StarlingMVCConfig = new StarlingMVCConfig();
config.eventPackages = ["com.mygame.events"];
config.viewPackages = ["com.mygame.views"]; var beans:Array = [new GameModel(), new ViewManager(this), new Command(DoSomethingEvent.DO_SOMETHING, DoSomethingCommand)]; starlingMVC = new StarlingMVC(this, config, beans);
}
}
}

这将映射事件到Command。command类可以像其它bean一样接收注入,但不能接收事件,事件也只在执行单个command的周期内存在。在command内将执行的方法被标为[Execute]标签。

package com.mygame.commands
{
import com.mygame.events.NavigationEvent;
import com.mygame.models.BubbleModel; import starling.events.EventDispatcher; public class DoSomethingCommand
{
[Dispatcher]
public var dispatcher:EventDispatcher; [Inject]
public var bubbleModel:BubbleModel; [Execute]
public function execute(event:DoSomethingEvent):void
{
trace("did something!");
}
}
}

所上所示,当DoSomethingEvent.DO_SOMETHING事件被派发时,StarlingMVC将创建一个DoSomethingCommand的实例,执行execute方法,然后销毁它。Command类可以在标签中包括一个runOnce的可选参数。

package com.mygame.views
{
import com.creativebottle.starlingmvc.StarlingMVC;
import com.creativebottle.starlingmvc.config.StarlingMVCConfig;
import com.creativebottle.starlingmvc.views.ViewManager;
import com.mygame.models.GameModel; import starling.core.Starling;
import starling.display.Sprite; public class GameMain extends Sprite
{
private var starlingMVC:StarlingMVC; public function GameMain()
{
var config:StarlingMVCConfig = new StarlingMVCConfig();
config.eventPackages = ["com.mygame.events"];
config.viewPackages = ["com.mygame.views"]; var beans:Array = [new GameModel(), new ViewManager(this), new Command(DoSomethingEvent.DO_SOMETHING, DoSomethingCommand, true)]; starlingMVC = new StarlingMVC(this, config, beans);
}
}
}

在这个例子中,一个command bean以这样的语句被添加:new Command(DoSomethingEvent.DO_SOMETHING, DoSomethingCommand, true)。最后的参数true,标识该comand只被运行一次。所以,当DO_SOMETHING事件被派发时,DoSomethingCommand的实例被框架创建,执行,最后销毁,并从映射中移除。这个功能在初始化时非常有用(译者注:指执行一次)。

EventMap

EventMap is a utility class for creating and managing event listeners. Using EventMap exclusively to create listeners within your class makes cleanup very easy.

EventMap是一个创建、管理事件监听的工具类。使用EventMap创建的事件监听易于清理。

package com.mygame.mediators
{
import com.creativebottle.starlingmvc.events.EventMap; public class GameMediator
{
private var eventMap:EventMap = new EventMap(); [ViewAdded]
public function viewAdded(view:Game):void
{
eventMap.addMap(view.playButton,TouchEvent.TOUCH, playButtonTouched);
eventMap.addMap(view.instructionsButton,TouchEvent.TOUCH, instructionsTouched);
} [ViewRemoved]
public function viewRemoved(view:Game):void
{
event.removeAllMappedEvents();
} private function playButtonTouched(event:TouchEvent):void
{ } private function instructionsButtonTouched(event:TouchEvent):void
{ }
}
}

Juggler

Starling的juggler用于管理游戏内的所有动画。对于一个使用Juggler便利的类,必须实现IAnimatable接口、定义

advanceTime(time:Number)

方法。全局的juggler引用可以通过这个实例属性访问:Starling.juggler。并且,这个属性可以使用[Juggler]标签被直接注入到bean中。(译者注:StarlingMVC1.1源码有一个专门的Processor用于处理Juggler的注入)

 package com.mygame.mediators
{
import com.creativebottle.starlingmvc.events.EventMap; public class GameMediator implements IAnimatable
{
[Juggler]
public var juggler:Juggler; [ViewAdded]
public function viewAdded(view:Game):void
{
juggler.add(this);
} [ViewRemoved]
public function viewRemoved(view:Game):void
{
juggler.remove(this);
} public function advanceTime(time:Number):void
{
// do some animation logic
}
}
}

ViewManager

ViewManager是一个工具类,通过它可以用来在舞台上添加删除视图。当我们创建ViewManager事例的时候,我们需要传递一个根显示对象。这样我们通过ViewManager可以在Starling的任意位置方便的添加可视化交互内容。

设置视图

调用setView将会移除已有的视图并且添加新的视图。ViewManager处理实例化视图,并将其添加到堆栈中。

package com.mygame.controllers
{
public class NavigationController
{
[Inject]
public var viewManager:ViewManager; [EventHandler(event="NavigationEvent.NAVIGATE_TO_VIEW", properties="viewClass")]
public function navigateToView(viewClass:Class):void
{
viewManager.setView(viewClass);
}
}
}

添加视图

调用addView方法将在现有视图上添加一个新的视图。这里通过addView方法将GameHUD类型的视图添加到现有视图管理器中。

package com.mygame.views
{
public class Game
{
[Inject]
public var viewManager:ViewManager; private var hud:GameHUD; [PostConstruct]
public function postConstruct():void
{
hud = new GameHUD(); viewManager.addView(hud);
}
}
}

移除视图

通过调用removeView可以删除堆栈中制定的视图。

移除所有视图

调用removeAll可以移除堆栈中存在的所有视图。当你调用setView()的时候这个方法会被自动调用。

StarlingMVC Framework中文教程的更多相关文章

  1. Django REST FrameWork中文教程2:请求和响应

    从这一点开始,我们将真正开始覆盖REST框架的核心.我们来介绍几个基本的构建块. 请求对象REST框架引入了Request扩展常规的对象HttpRequest,并提供更灵活的请求解析.Request对 ...

  2. Django REST framework 中文教程1:序列化

    建立环境 在我们做任何事情之前,我们将使用virtualenv创建一个新的虚拟环境.这将确保我们的包配置与我们正在开展的任何其他项目保持良好的隔离. virtualenv envsource env/ ...

  3. Django REST FrameWork中文教程3:基于类的视图

    我们也可以使用基于类的视图编写我们的API视图,而不是基于函数的视图.我们将看到这是一个强大的模式,允许我们重用常用功能,并帮助我们保持代码DRY. 使用基于类的视图重写我们的API 我们将首先将根视 ...

  4. director.js:客户端的路由---简明中文教程

    1.引子 最近学用director.js,那是相当的简单易学易使用.不过开始学的时候,搜搜过后,却没有发现相关的中文教程.于是决定硬啃E文,翻译备用的同时也当是给自己上课并加深对它的理解. direc ...

  5. Groovy中文教程(链接收藏)

    学习Gradle前,需要有一个Groovy语言的基础,以免被Groovy的语法困扰,反而忽略了Gradle的知识.这里有一个Groovy的简明中文教程文档,可以快速学习Groovy的一些语法:http ...

  6. webstorm的中文教程和技巧分享

    webstorm是一款前端javascript开发编辑的神器,此文介绍webstorm的中文教程和技巧分享.webstorm8.0.3中文汉化版下载:百度网盘下载:http://pan.baidu.c ...

  7. 读w3c中文教程对键盘事件解释的感想 -遁地龙卷风

    写这篇博文源于w3c中文教程对键盘事件的解释, onkeydown 某个键盘按键被按下 onkeypress 某个键盘按键被按下并松开 onkeyup 某个键盘按键被松开 可在实践中发现 只注册key ...

  8. wxPython中文教程入门实例

    这篇文章主要为大家分享下python编程中有关wxPython的中文教程,分享一些wxPython入门实例,有需要的朋友参考下     wxPython中文教程入门实例 wx.Window 是一个基类 ...

  9. Google Analytics统计代码GA.JS中文教程

    2010-12-06 11:07:08|  分类: java编程 |  标签:google  analytics  ga  js  代码  |举报|字号 订阅     Google Analytics ...

随机推荐

  1. SELECT样式,兼容IE6

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. 【管理工具】Git的安装与使用

    公司与公司合并,需要学习一下git的使用.从网上找了一篇资料,完全满足需求,先赞一个. http://www.cnblogs.com/Bonker/p/3441781.html 下面记录一下自己的安装 ...

  3. 【移动开发】安卓Lab2(01)

    本次Lab需要用到Google Map的API,分享学习一下Google Map的知识 需求: 界面: 1. 主界面(map界面): 提供了指定的学校校园地图图片,不能用Google的API生成图片 ...

  4. Codeforces 367

    A. Sereja and Algorithm 水题不解释. B. Sereja ans Anagrams 模p同余的为一组,随便搞. C. Sereja and the Arrangement of ...

  5. Spring入门(8)-基于Java配置而不是XML

    Spring入门(8)-基于Java配置而不是XML 本文介绍如何应用Java配置而不是通过XML配置Spring. 0. 目录 声明一个简单Bean 声明一个复杂Bean 1. 声明一个简单Bean ...

  6. mysql优化(一)

    1.选取最适用的字段属性  MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得 ...

  7. C#的dll被其他程序调用时,获取此dll正确的物理路径

    当C# dll被其他程序调用时,用Application.StartupPath获取的dll路径并不一定是此dll的物理路径,有可能是调用程序的路径. 以下方法或者能够获取dll正确的物理路径(未经过 ...

  8. 使用truss、strace或ltrace诊断软件的“疑难杂症”

    简介 进程无法启动,软件运行速度突然变慢,程序的"Segment Fault"等等都是让每个Unix系统用户头痛的问题,本文通过三个实际案例演示如何使用truss.strace和l ...

  9. JS一定要放在Body的最底部么? 聊聊浏览器的渲染机制

    请参看文章 https://segmentfault.com/a/1190000004292479 网上的回答: 1.js加载会阻塞其它内容加载,使页面加载时间更长,尤其是js文件太大,有的页面js文 ...

  10. [转]JSON.stringify 语法实例讲解

    原文地址:http://www.jb51.net/article/29893.htm 作用:这个函数的作用主要是为了系列化对象的. 可能有些人对系列化这个词过敏,我的理解很简单.就是说把原来是对象的类 ...