Flex Viewer 解析(三)Flex Viewer架构解析

OK!进入主题,本小节我们一起来探究一下Flex Viewer的庐山真面目!

3.1  Flex Viewer主席团

com.esri.viewer.managers包中,汇集了Flex Viewer中所有的Manager。这些Manager各个肩负重任,他们虽隐身幕后,却是Flex Viewer良好运转的关键,我们不妨称之为主席团成员。

1)     ConfigManager

Flex Viewer通过配置文件来组织数据、功能和UIConfigManager的责任是适时读取配置文件,对配置文件进行解析,然后将解析结果分发出去,由其他需要使用配置文件数据的模块接收。

2)     DataManager

Flex Viewer各个部分之间需要共享数据,比如说WidgetWidget之间数据共享。DataManager提供了一种数据共享的方案,任何模块都可以通过DataManager把数据贡献出来,供其它模块使用。 DataManager的关键职责是把共享数据保存在内存中,任何时候都可以从DataManager获取需要的共享数据。

3)     MapManager

MapGIS应用的基础。MapManager解决了Map的问题。MapManager不是对Map的简单封装,而是提供了所有与Map相关的操作,比如根据配置文件加载地图,放大、缩小这些基本操作,画图,在地图上显示信息框,图层控制等等。如果在某个自定义Widget中,想要画一个多边形,不必new一个DrawTool,发个消息告诉MapManager你想画个多边形即可;如果你想在地图上某个点上显示一些信息,同样发个消息告诉MapManager就行了。MapManager会很友好地帮我们完很多工作,我们只需发个消息知会一声。

4)     ScriptingManager

预留,尚未使用。

5)     SecurityManager

预留,尚未使用。

6)     UIManager

Flex Viewer用户体验之所以风格统一,是因为UIManager做了大量的工作。在配置文件中,有如下脚本,UIManager会根据这一信息对UI的样式进行配置。

<style>

               <colors>

0xFFFFFF,0x333333,0x101010,0x000000,0xFFD700

</colors>

               <alpha>0.8</alpha>

</style>

7)     WidgetManager

顾名思义,WidgetManager是对Widget进行管理的组件。WidgetManagerWidget的管理包括根据配置文件创建Widget信息列表、加载Widget、布局Widget、关闭Widget等。WidgetManager提供四种Widget布局方式:自由布局(float)、水平布局(horizontal)、垂直布局(vertical)和固定布局(fix)。自由布局Widget可以拖动,水平布局、垂直布局和固定布局Widget完全有WidgetManager管理,不可拖动;四种布局方式中,固定布局Widget不可改变窗口大小。

3.2  Flex Viewer松耦合的关键

系统耦合度是决定系统灵活性与可维护性的关键。Flex Viewer的松耦合设计是其健壮的关键因素之一。那么,是什么保证了Flex Viewer的松耦合呢?

“事件!事件!还是事件!”

事件是Flex Viewer松耦合的关键。在3.1中多次提到了“消息”,物化到Flex Viewer中就是事件。不同的模块通过事件彼此交互、传递数据,保证了各模块之间的松耦合,彼此不必相知,却能紧密合作。ViewerContainerEventBusAppEvent组成了Flex Viewer事件机制的基础。当然,Flex Viewer事件机制的基础是Flex的事件机制。

1)     EventBus

继承自EventDispatcher,使用了单例模式。EventBus是全局的事件派发器,为Flex Viewer中的不同模块之间的交互提供便利。有了EventBus,不同模块之间的交互无需彼此调用对方的方法,只需派发/监听消息即可。

2)     AppEvent

继承自Event,在Flex Viewer中被用来当做消息和数据的载体,在不同的模块之间传递数据。AppEvent定义了Flex Viewer中需要的所有事件类型,也就是那些公共的字符串常量。通常,系统层面需要添加的事件也都定义在AppEvent中。

3)     ViewerContainer

继承自Group,使用了单例模式,是Flex Viewer中各个模块的容器。Flex Viewer中调用ViewerContainer最多的三个方法是:addEventListener()dispatchEvent()showError()。我们可以在任何需要对某类AppEvent事件进行监听的地方通过addEventListener()方法添加监听,可以在任何需要派发某类AppEvent事件的地方通过dispatchEvent()方法派发事件,可以在任何需要显示Error信息的地方通过showError()方法显示Error信息。如果通读Flex Viewer代码,会发现,AppEvent的监听与派发随处可见。

Flex Viewer松耦合的关键因素还有Widget的设计和实现,这部分内容将在后面的小节涉及,在此按下不表。

至此,我们的讨论涉及到了Flex Viewer中的绝大部分模块,先来看一下Flex Viewer的整体结构,如图3.1所示。图中最下方的Control WidgetsBusiness Widgets尚未提及,我们将在3.4中涉及这部分内容。

 

         3.1 Flex Viewer整体结构

3.3  初始化那些事儿

在浏览器地址栏输入Flex Viewer的地址,经过短暂等待,当她华丽丽地展现在我们眼前,你是否想过在这短暂的等待中,Flex Viewer都做了哪些事情呢?本小节我们来探讨Flex Viewer初始化那些事儿。注意,我们这里所说的Flex Viewer初始化,不是Flex概念中组件生命周期的初始化部分,而是指Flex Viewer在可以与用户交互之前,所做的准备工作。

 

3.2 Flex Viewer初始化过程

3.2小节中,我们强调通过使用事件,Flex Viewer将各模块之间充分解耦。实际上,事件也伴随着Flex Viewer初始化的整个过程。Flex Viewer的初始化过程如图3.2所示。

1)     首先观察一下ConfigManager的构造方法,其中有这样一句代码:

ViewerContainer.addEventListener(ViewerContainer.CONTAINER_INITIALIZED, init);

也就是说,ConfigManager实例在构造期间就通过ViewerContainerEventBus的单例添加了对CONTAINER_INITIALIZED事件的监听,一旦ViewerContainer在别的地方派发了CONTAINER_INITIALIZED事件,ConfigManager将响应该事件,开始读取配置文件、解析配置文件,构造ConfigData数据,最后将ConfigData连同CONFIG_LOADED事件派发出去,见下面代码:

ViewerContainer.dispatchEvent(new AppEvent(AppEvent.CONFIG_LOADED, configData));

2)     我们再观察一下UIManagerWidgetManagerMapManager的代码,在各自的初始化代码中,都可以找到下面一句代码,此处不再解释:

ViewerContainer.addEventListener(AppEvent.CONFIG_LOADED, config);

3)     最后,问题的关键在于CONTAINER_INITIALIZED事件何时何地被派发?我们观察一下ViewerContainerinit()方法,其中有下面这句代码:

ViewerContainer.dispatch(ViewerContainer.CONTAINER_INITIALIZED);

init()方法是ViewerContainercreationComplete事件的响应方法。也就是说ViewerContainer初始化结束才是Flex Viewer初始化的开始。

Flex Viewer初始化的脉络已经相当清晰,ConfigManagerUIManagerWidgetManagerMapManager在各自的初始化过程中对相应的事件进行监听,一旦ViewerContainer初始化完成,派发出CONTAINER_INITIALIZED事件,其它的准备工作将顺其自然,水到渠成。

我们注意到,初始化过程所涉及的各个模块都是相互透明的,彼此并不知道有对方的存在,而这些模块之所以能够亲密协作,关键就在于它们都只关心事件,事件机制使得这些模块之间实现松耦合。实际上,事件充斥着Flex Viewer的各个角落,随着对Flex Viewer理解的逐渐深入,对这一点的体会将更加明显。

3.4  Widget设计及实现

 
一个Widget是对一组相关操作的封装,这些相关操作完成某项特定业务功能。Widget不仅可以调用地图资源,也可以访问服务器端资源。Widget基于Flex Module,编译后是独立的swf文件,这样一来,将具体的业务逻辑封装在Widget中,减小了系统主体的体积,在业务功能较多时,可显著缩短系统加载时间。加之面向接口编程和依赖注入思想的应用,Flex Viewer中的Widget可以独立开发,通过配置文件决定提供哪些Widget,从而决定系统提供哪些业务功能。可以把Widget理解为“插件”。这种灵活的“插件”机制是如何实现的呢?下面我们了解一下Widget编程模型,如图3.3所示。

 

 

3.3 Widget编程模型

Widget分为两种,Control WidgetBusiness WidgetControl Widget是指控制组件,比如NavigationWidgetHeaderControllerWidgetOverviewMapWidget等,这些Widget提供系统级别的功能,不针对具体业务功能;Business Widget是指业务组件,比如SearchWidgetBookmarWidgetGeoRSSWidget等,这些Widget提供具体业务功能。两种Widget都继承自BaseWidget,都由WidgetManager来管理,不同的是,在WidgetManager中有一个WidgetContainer来专门管理Business Widget

两种Widget有共同的父类BaseWidgetBaseWidget实现了接口IBaseWidget,两者也就有了共同的接口。WidgetManager通过IBaseWidget来管理Widget,与具体的Widget解耦。Flex Viewer此处使用面向接口编程和依赖注入,实现了主体系统与Widget的松耦合。

u  IBaseWidget

该接口定义了WidgetManagerWidget进行交互的方法,BaseWidget实现了这个接口。

u  BaseWidget

该类是所有Widget的基类。只要某一组件继承自BaseWidgetWidgetManager即可对其进行管理。由于BaseWidget继承自Module,每一个Widget都将编译成独立的swf文件。

但两种Widget在具体实现上有所不同。Flex ViewerBusiness Widget提供了统一的UI基类和接口,也就是WidgetTemplateIWidgetTemplate。通常情况下,Control Widget都会使用自定义UI,但是这不是必须的。

u  IWidgetTemplate

该接口定义了BaseWidgetWidgetTemplate交互的方法。WidgetTemplate实现了这一接口。

u  WidgetTemplate

该类是IWidgetTemplate的一种默认实现,在具体的Widget实现中,同样可以使用自定义的WidgetTemplate,只要实现IWidgetTemplate接口即可。WidgetTemplateWidget提供基本UI控件,包括窗口面板、带有图片按钮的标题栏等。使用Flex Viewer实现的WidgetTemplate,开发人员可以将更多的精力和时间放在实现业务逻辑上。

需要说明的是,Widget的设计在Flex Viewer 1.x版本和2.x版本中有所区别。在1.x中不存在Control Widget,比如菜单组件,菜单项是可配置的,但是菜单组件本身是不可配置的。2.x版本以后,Widget的概念扩大了,Flex Viewer中,凡是能看到的组件都是Widget,这样一来,控制组件可以像业务组件一样可配置,比如HeaderControllerWidget,灵活性大大提高。

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值