viewer,Flex Viewer解析 (转)

Flex Viewer是ESRI公司推出的可以高效开发基于WEB的地理信息应用系统的一种基本架构。它帮助你屏蔽了底层繁琐的操作,比如通信机制。此框架和服务器端的通信是基于Web Service的。在服务器端,发布出你的服务,比如地图服务,前端只需简单的调用操作。开发人员只需关注你的功能模块设计。
1、Widget开发
Flex Viewer中,采用Widget的方式进行模块设计。每一个模块都是一个Widget,具体说是BaseWidget。
类的关系如上图所示,IWidgetTemplate和IBaseWidget是接口,WidgetTemplate和BaseWidget分别实现它们。在初始化BaseWidget时,会依赖IWidgetTemplate去初始化每个模块的title、icon等属性。
上图很清晰地给出了一个Widget的处理流程图。要说明的是,由于BaseWidget继承了Module,所以每一个Widget都是一个 Module。好处很多,延迟加载,高内聚性,模块之间几乎没有侵入性。
2、总体上Container结构
图中提到了Flex Viewer Container,整个框架看着是一个大的Container,而这个Container是有一些高内聚低耦合的组件组成,如下图:
这里可以看到整个框架是由几个组件构成,ConfigManger用来管理配置文件,WidgetManger管理所有的Widget。等等。。。 SiteContainer.mxml持有对这些组件的引用。
3、核心事件处理
因为Flex采用事件机制,那么,在Flex Viewer中各组件(* Manager)之间通信时怎样完成的呢?这里就提到了Flex Viewer中核心类:EventBus. 注意到EventBus采用单例模式,保证在整个框架中只有一个EventBus。SiteContainer.mxml中提供了一系列静态的代理方法可以访问EventBus。
当上图中每一个组件(* Manager)初始化的时候,都会监听相应的事件;而SiteContainer会把监听任务委托给EventBus,并由EventBus统一分发事件。通过这种发布/订阅的消息模式,组件之间可以轻易交互而不用直接访问组件中的方法。所以,这种方式使组件解耦,可复用性很高。
EventBus中使用的事件类型都是由AppEvent.as这个类定义,它负责帮助EventBus在各个组件间传递消息。它是一个自定义事件,负载着数据传递的功能。
总结一下吧,Flex Viewer是基于事件机制,使用模块化设计,每一个模块负责各自的任务,互不侵入。模块之间的消息传递通过EventBus实现。自定义Widget编译完在各自的配置文件中配置路径、图标等信息,并在config.xml中添加此配置文件的路径信息,最后由ConfigManager统一加载 config.xml文件
FlexViewer是ESRI公司利用Flex技术,基于本身已开发好的Flex API包开发的一个成熟的WebGIS实例框架。其完全是开放的,可以从官方网站上的Code Gallery直接下到源码。
FlexViewer1.3下载网址:
http://resources.esri.com/arcgisserver/apis/flex/index.cfm?fa=codeGalleryDetails&scriptId=15905
下载完成后解压直接导入Adobe Flex 3 Builder项目即可使用。
FlexViewer自从09年在社会上出现以来,引发了一场热烈的WebGIS开发热潮。其完美的将Server Flex API的优点展现出来,使很多第一次见到这种体验效果的人心潮澎湃。Flex API的最大的最大优势也许就在此吧。就是他依靠了一个具有很好用户体验效果的平台FLEX
具有一般程序经验的程序员一般应该都可以看懂AS代码,所以基于Flex的WebGIS开发应该是不难的,就是一个API包,吃透了就是屈指可数的功能,基本上就是简单的地图操作,当然分析功能还是有的,那就不是Flex API包来完成的了。在此不再冗述。
近些时间,总有人问我关于FlexViewer的问题,而且都是一些相对基础的问题。对FlexViewer的结构不是太理解,因此将自己对其的理解写成一个解析,内容我将会在以后的时间里陆续的传到blog里面,供网友参阅。不足之处或者错误之处难免会有,请大家批评指正。
另外大家也可以从esri的Code Gallery里面下载到很多关于FlexVIew的扩展功能。
FlexViewer1.3下载网址:
http://resources.esri.com/arcgisserver/apis/flex/index.cfm?fa=codeGalleryDetails&scriptId=15905
Code Gallery地址
http://resources.esri.com/arcgisserver/apis/flex/index.cfm?fa=codeGallery
FlexViewer2.0下载网址(flexviewer-2.0beta2-src.zip)
http://www.arcgis.com/home/item.html?id=3f6a0bfee48949a88df50bf7686ec72a
http://help.arcgis.com/en/webapps/flexviewer/
http://resources.arcgis.com/gallery/video/arcgis-api-for-flex
Flex Viewer解析 二 结构(转)1.结构图以及解析
下图是ESRI提供的开发帮助里面对其结构的一个描述图,本人做了一些归类:

viewer,Flex Viewer解析 (转)

A部分:这一部分是项目中的组件列表,包括一些配置文件、Module(就是Widget)、组件等等。这些组件在没有经过组织之前是完全孤立的。它们主要完成一些界面显示和业务逻辑。
B部分:该部分的主要功能就是将A部分中相互完全孤立的文件列表,不管是业务层还是界面层进行一个组织,将他们之间关联起来,便于程序的统一管理和开发。其中对于将这些文件或者组件综合起来的一个非常重要的一个内容就是container(在viewer中叫做SiteContainer容器),关于 container是如何组织这些组件的,在SiteContainer解析一文中将会详细阐述。
C部分:我们可以将该部分称作数据层,也就是说这一层是提供数据的,不管是地图数据还是常规数据,都是通过这一层获取的,关于这一层在Viewer中并不明显,其贯穿于整个系统的各个角落。本人愚见,此处也是Viewer需要改进的地方。
在下面的文章里,我们主要基于这三部分对FlexViewer进行解析。
理解了Viewer的这三部分,那么在Viewer中是如何具体的进行文件或者说组件组织的 呢?
2.文件组织
首先我们还是看下Viewer的效果图,同样将其分成几个部分,我们在将这些部分进行一一介绍。
我同样将其分成三个大的组件部分。

viewer,Flex Viewer解析 (转)

A部分:该部分是地图显示部分,也是系统的主体部分,地图的一些显示配置和基本操作都在该部分中。对于该部分的定义,我们在Viewer中不难找到,那就是FlexVIew文件夹下面的
com\esri\solutions\flexviewer\MapManager.mxml
该文件中定义个,地图的添加以及一些地图的基本操作。
map = new Map();
map.id = "map";
map.zoomSliderVisible = false;
map.addEventListener(MapEvent.LOAD, mapLoadComplete);
this.addChild(map);
这几行代码完成了对map控件的添加,下面的部分就是图层的添加以及一些配置,包括一些工具定义:
navToolbar = new Navigation();
navToolbar.map = map;
drawToolbar = new Draw();
drawToolbar.map = map;
这两行代码,为地图添加了一个浏览工具和一个绘图工具。
B部分:该部分是一个控制条,用来控制整个系统的用户操作。其主文件为:
com\esri\solutions\flexviewer\Controller.mxml
打开之后我们发现其显示部分很简洁:
horizontalCenter="0" y="{banner.height - 20}"/>
其实其使用了一个定义好的组件Banner,这个组件才是这个控制条信息的主体部分。而control只是为这个组件提供必须的配置信息。
Banner组件位于components文件夹下,打开它,仔细查看其中的内容,我们就可以明白Viewer里面的B部分是怎么出来的了。
然后我们说说B部分的菜单是如何出来的。在Controller仅仅的两行设计代码里面我们可以看到有个叫做menuContainer的HBox,他就是负责显示菜单的。在程序的配置文件加载完成后,这个界面就会执行对菜单的配置,也就是下面的一个函数:
private function configureMenus():void
{
for (var i:Number = 0; i < configData.configMenus.length; i++)
{
var menuId:String = configData.configMenus.id;
var menuLabel:String = configData.configMenus.label;
var menuIcon:String = configData.configMenus.icon;
var menuItems:Array = configData.configMenus.items;
var controllerMenu:ControllerMenu = new ControllerMenu();
controllerMenu.id = menuId;
controllerMenu.menuLabel = menuLabel;
controllerMenu.menuImage = menuIcon;
controllerMenu.menuCollection = new ArrayCollection(menuItems);
menuContainer.addChild(controllerMenu);
}
var bw:Number = configData.configMenus.length * 90;
if (bw > banner.minWidth)
banner.width = bw;
}
这里面使用了另外一个组件ControllerMenu,其定义位于Banner.mxml同目录下的ControllerMenu.mxml中,这个组件就是完成主菜单定义的主要控件。对于子菜单的定义我们在ControllerMenu中可以看到这句代码:
itemLabel ="{menuRepeater.currentItem.label}"
itemIcon ="{menuRepeater.currentItem.icon}"
itemRuleVisible ="{menuRuleVisible(menuRepeater.currentIndex)}"
itemAction ="{menuRepeater.currentItem.action}"
itemValue ="{menuRepeater.currentItem.value}" />
这个Repeater就是用来完成子菜单信息绑定的。其中使用了关于子菜单的组件ControllerMenuItem,我们打开这个子菜单的定义,可以清楚地看到关于子菜单的点击事件和一些效果代码。这就是菜单的实现方式。
以上就是Viewer左上侧控制条的实现流程。
C部分:这一部分的实现相对比较复杂,主要是在其管理上面,再加上其使用Module的方式加载显示,所以感觉上相对复杂。
Tags:  viewer

延伸阅读

最新评论

发表评论