Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3246014
  • 博文数量: 530
  • 博客积分: 13360
  • 博客等级: 上将
  • 技术积分: 5473
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-13 13:32
文章分类

全部博文(530)

文章存档

2017年(1)

2015年(2)

2013年(24)

2012年(20)

2011年(97)

2010年(240)

2009年(117)

2008年(12)

2007年(8)

2006年(9)

分类:

2010-05-15 17:37:59

最后更新日期:2010年7月22日

    由于parsley可以在配置文件内定义托管对象,包括视图元素。对于FLEX应用程序,这种方法并不理想,因为你可能想在你的MXML文件的组件中声明你的组件,而不是parsley配置文件中声明组件。因此,你需要一个机制将parsley配置文件内的对象与MXML文件中的组件联系起来。

    parsley在本章提供了使用案例。

7.1 初始化视图注入(Initializing View Wiring Support)

    对于视图注入,每个上下文需要一个或多个"视图根",视图根是一个DisplayObject对象,用来监听来相关上下文中组件的事件。你可以用MXML标签初始化上下文或通过编程实现。

用MXML标签初始化上下文

    在FLEX应用程序中,你可以使用ContextBuilder标签(version 2.2版本引入)。这将用自动在视图根上使用文档对象(document object)。

           

    你自己想直接指定视图根的情况很罕见,可以如下配置:

     viewRoot="{someOtherDisplayObject}"/>

上下文编码初始化

    如果你通过程序初始化框架,视图根必须描述:

    XML配置(XML configuration)

          var viewRoot:DisplayObject = ...;
XmlContextBuilder.build("bookStoreConfig.xml", viewRoot);

    多个配置机制

          var viewRoot:DisplayObject = ...;
var builder:CompositeContextBuilder = new DefaultCompositeContextBuilder(viewRoot);
FlexContextBuilder.merge(BookStoreConfig, builder);
XmlContextBuilder.merge("logging.xml", builder);
builder.build();

7.2 明确组件注入(Explicit Component Wiring)

    如果你想将一个组件直接注入到组件自身所在的上下文中,你可以有二个选择。第一,你可以使用标签:

                    xmlns:mx=""
xmlns:parsley="">





    在FLEX4中,这将需要使用 标签。例如上例组件Panel将注入到上下文。你可以精确描述准备注入的对象,这个对象甚至可以不是组件:

                      xmlns:mx=""
xmlns:parsley=""
xmlns:view="myproject.view.*">


target="{model}" />




    本例中,我们声明一个表示层model,并将这个model注入到上下文中。万一视图组件自身不是由parsley容器管理,你就不能在该视图组件内设置任何parsley元标签。这个model主要用于性能优化。参见下一节的第二部分将重点谈谈如何避免大型组件类的过多反射.


在flash应用程序中注入

    在flash应用程序中,本章的注入方式并不能用。没有MXML去定义视图,我们经常直接在XML配置文件或actionscript配置文件中声明与视图相关的对象。因此,这里并不需要明确描述如何注入他们。
    万一你不想在上下文中定义视图,而是想使用动态注入上下文方式,这样你就能派发一个事件,就歇脚在FLEX中使用了 标签一样。为了达到这种效果,你首先应该描述视图根,去捕获这些bubbing事件。

       var viewRoot:DisplayObject = ...;
ActionScriptContextBuilder.build(MyConfig, viewRoot);

这样,每个在视图根中描述的DisplayObject 对象,当它被添加到stage中,就可以派发一个注入的事件。

public class MyView extends Sprite {

    function MyView () {
        addEventListener(Event.ADDED_TO_STAGE, configure);
    }
   
    private function configure () : void {
    dispatchEvent(new Event("configureView", true));
    }
   
    /* ... */
   
}

7.3 无反射组件注入(Component Wiring without Reflection)

    Parsley对所有管理对象和组件反射操作代价很大,主要是由于其属性、方法和事件太多。一个组件可能花费30毫秒。parsley维护一个内部反射缓存,如果你使用了大多的不同组件,缓存的意义就不大了。一个小的应用程序,这种花费很少,但是对于大型系统,就要重点关注了。本节内容通过一些案例让你避免性能大幅下降。

    为了允许性能优化,Parsley 2.2引入标签FastInject

                    xmlns:mx=""
xmlns:parsley=""
xmlns:view="myproject.view.*">


import com.bookstore.model.MyPanelPM;

public var model:MyPanelPM;
]]>







    这有点类似与标记和属性的目标的例子。这个模型将被注入到上下文中。但不同的是,在前一个例子中,模型是由内部的组件内的标签创建,然后由框架配置已实例化的模型对象。在这个例子中,容器panel创建模型对象,然后注入到组件中。这种方法的主要优点是,该模型可以在组件之间共享,而前例不行。这只是解决性能是一个方法。

    FastInject标签也允许通过子标签定义多个注入:

        



    如果你想执行所有的注入的话,必须将它们合并为单一的父标签。如果你使用独立的标签,你需要手动检查哪些已经注入已处理。在上面的例子可以保证,只有所有的注入都执行后,init方法只会被调用。

    标签的事件creationComplete或addedToStage与组件事件类似,但是并不相同。当相应的组件事件被捕获且注入已经执行完,才找一个合适的机会初始化组件。


7.4 自动组件注入(Automatic Component Wiring)

    自Version2.2后,你还可以通过自动视图注入,避免为单个组件类添加具体配置。但是parsley存在多上下文环境,自动注入会导致不知道哪些上下文中。目前只能基于他们所处的视图层次的位置。一个组件被注入到最接近的上下文中。

    因为这个功能很新,没有严格测试,因此,必须注意parsley的版本号:

    MXML

         



    ActionScript

         GlobalFactoryRegistry.instance.viewManager.autowireFilter.enabled = true;

    在第一个上下文创建之前,上一行语句必须执行。正如你所期望的,autowireFilter可是选 的。你可以实现自己的选择逻辑,告诉框架哪个组件应该注入。默认仅注入MXML或XML文件中标签的组件。这种方式真正做到了统一配置。你在一个配置文件中就可以看到托管的视图和对象。一个示例配置片段可能是这样的:

        










    这里简单的展示了视图定和相关视图模型。仅仅这里的视图将注入到上下文中。本例中,我们还使用了空视图标签,你也可以象对象标签一样隐藏标签,参见

    你也可以实现你自定义的autowire过滤器,最简单的方式是继承DefaultViewAutowireFilter并覆盖filter方法:

    public class MyAutowireFilter extends DefaultViewAutowireFilter {

public override function filter (view:DisplayObject) : ViewAutowireMode {
if (... someCondition ...) {
return ViewAutowireMode.ALWAYS;
}
else {
return ViewAutowireMode.NEVER;
}
}

}

    最终,使用filter如下所示:

         GlobalFactoryRegistry.instance.viewManager.autowireFilter = new MyAutowireFilter();

7.5 元数据配置(Metadata Configuration)

    大多数情况下,元数据是够用的,组件上的元数据标签与容器创建的对象具有相同的效果。

            xmlns:mx=""
addedToStage="dispatchEvent(new Event('configureView', true));">


import com.bookstore.events.*;
import com.bookstore.model.*;

[Bindable]
private var user:User;

[Inject]
public var model:LoginPanelPM;

[MessageHandler]
public function handleLogin (event:LoginEvent) : void {
this.user = event.user;
}
]]>






    一些开发人员要避免添加过多的逻辑到组件中。大部分情况下,在组件的表示模型类上使用parsley标签[Inject]封装所有的逻辑和数据。


7.6 MXML和XML配置配置(MXML and XML Configuration)

    自Version2.2,你可以在MXML或XML上配置视图。在两种情况下会很方便:一、你可以在不同的脚本中使用相同的组件类;二、你可能想使用配置机制去描述如同演示的自动注入。

    这个功能已用在了Flicc中,当它被注入到上下文中,容器将配置信息作用到视图上。作用于注入组件的配置信息将根据ID或type匹配:

     



    这看上去象一般对象的配置信息。视图标签的使用说明,parsley等到任何匹配的组件动态地获取注入的上下文,应用配置后,再创建该类的实例。

    Parsley首先根据ID匹配。ID既可以是FLEX组件的名字,也可以是配置标签的ID

          

    如果根据ID没有匹配,框架将根据类型匹配。如果定义含糊,则抛出错误。如果没有匹配类型,parsley将使用传统机制去处理元数据。


7.7 组件生命周期(Component Lifecycle)

    由于FLEX组件与IOC容器有关联,组件生命周期与直接定义在容器内的对象是不同的。这个由标签[Init]和[Destroy]决定。

方法标签[Init] Methods annotated with [Init]

    对于一个声明在parsley配置文件中的对象,容器创建并配置好对象后才开始执行这些方法。对于一个动态注入的FLEX组件,容器捕获组件派发的事件和所有的注入都注入后,才开始执行这些方法。

方法标签[Destroy]Methods annotated with [Destroy]

    对于一个直接在parsley配置文件内声明的对象,这些方法仅在容器被销毁并且调用Context.destroy()后执行。对于一个动态注入的FLEX组件,destroy方法将在组件从stage移出后调用。

    最后如果该组件的生命周期应该不依赖于它在stage上的时间花费,您可以切换此默认行为。你可以设置ViewManagerFactory属性,无论是在GlobalFactoryRegistry或CompositeContextBuilder.factories设置上下文。对于Flex这也可以配置的设置标签

        



    当组件从stage中移除后,以上设置使组件不会从上下文中移除。当需要不再注入时,替代这样一个组件必须派发"removeView"事件。

    最后,在单个组件上添加以下元数据:

        
[RemovedEvent("removeView")]


7.8 Flex Popups and Native AIR Windows

For Flex Popups and Native AIR Windows some extra step is required to tell the framework about them. This is because those are views which are disconnected from the view hierarchy below the main Application component. A Flex Popup usually sits somewhere right below the SystemManager. A Native AIR Window even comes with its own SystemManager. So you have to connect both manually to a Parsley ViewManager if you want to use view wiring in popups and windows. This is quite easy:

Flex Popup

[Inject]
public var context:Context;

private function showPopup () : void {
var win:TitleWindow = new TitleWindow();
// set properties
context.viewManager.addViewRoot(win);
PopUpManager.addPopUp(win, this);
}

AIR Window

[Inject]
public var context:Context;

private function openWindow () : void {
var win:Window = new Window();
// set properties
context.viewManager.addViewRoot(win);
win.open();
}

The removeViewRoot method of the ViewManager interface will not be called by application code directly in most cases, as the default implementation of the interface will automatically remove a view root when it is removed from the stage.


7.9 在模块化系统中视图注入(View Wiring in Modular Applications)

    下图展示了如何在模块化系统中进行视图注入,最重要的是如何人工连接FLEX的Popups和本地AIR容器到上下文。

    包含标签的Flex的组件,派遣一个冒泡事件得到了一个高于该层次结构中的下一个组件ViewManager侦听捕获。通过这种方式找到它的每个组件匹配上下文,这是重要的,因为一个组件加载到模块通常也需要访问该模块的配置。如果它注入到根上下文,它只会“看”上下文中的对象。

    图中的上下文C你会看到上下文有两个视图根:一个是加载模块的根组件,另一个是为弹出窗体打开的视图根。很明显,为什么手工连接popup是必要的:如果一个组件的级别比popup低,派遣一个冒泡事件在SystemManager结束,不能达到ViewManager在根坐在模块组成部分,所以我们必须设置第二个监听器。

    最后,这种机制是针对应用程序领域的:parsley的内部ModuleManager在根模块组件设置监听器,捕获ContextBuilders发出的事件,告诉应用程序如何使用。

    在某些罕见情况下,您可能要加载的Flex模块只包含了一些注入的视图类,但没有控制器,指挥,演示或域模式。你也许会跳过创建上下文,在这种情况会导致部分注入到根上下文。所以,你还是应该建立在模块中的根组件上下文,即使它是空的。这可以简单地透过根组件放入一个空标签

阅读(3291) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~