首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 媒体动画 > flex >

Flex运用ArrayCollection实现动态Tree

2012-09-21 
Flex使用ArrayCollection实现动态Tree接触Flex4一个多月,系统地了解了Flex4主要技术。近日想做一个Tree控件

Flex使用ArrayCollection实现动态Tree
接触Flex4一个多月,系统地了解了Flex4主要技术。近日想做一个Tree控件的Demo,但发现关于Flex4的很多书籍中主要描述的数据展现控件为DataGrid,List,几乎不涉及Tree,查阅Flex4官方API,看到了Tree控件的简单Demo,使用Flex4内置的XML数据结构填充Tree的dataProvider属性。数据源如下:

<fx:Declarations><fx:XMLList id="treeData"><node label="MailBox"><node label="Inbox"><node label="Marketing"/><node label="Product Management"/><node label="Personal"/></node><node label="Outbox"><node label="Professional"/><node label="Personal"/></node><node label="Spam"/><node label="Sent"/></node></fx:XMLList></fx:Declarations>

在Tree中指定dataProvider属性和labelField属性即可展示树。
<mx:Tree id="myTree" width="50%" height="100%"  dataProvider="{treeData}" labelField="@label" showRoot="true”></mx:Tree>

   但是在实际应用中,面对上万甚至上百万条的数据我们不可能使用静态树,更多是使用动态树。从网上查阅了很多,关于动态树的解决方案基本都是基于XML数据源的,即点击节点时调用RemoteService去Java服务端获取XML来展现子节点。这样的问题对于我来说,就是要在后台对数据库获取的数据进行XML格式的封装,前台也要对XML进行操作。方法不当的话,效率会很低下。我们更希望直接使用Java返回的List对象数组进行树的展示。即在前台使用ArrayCollection作为Tree的dataProvider。结合网上的资料,自己使用了如下的实现方案,在此总结一下。

Server端(Java)
使用VO来封装数据库的数据,其中需要有一个类型为List的children属性,由于Tree控件不像DataGrid,List控件,它拥有层次结构。
package com.ls.vo;import java.util.List;public class Spec {private String id;private String name;private String type;private List<Spec> children;public Spec(){}public Spec(String id, String name, String type) {super();this.id = id;this.name = name;this.type = type;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getType() {return type;}public void setType(String type) {this.type = type;}public List<Spec> getChildren() {return children;}public void setChildren(List<Spec> children) {this.children = children;}}

构建一个Spec的Service类实现业务操作。简单起见,将Service和Dao融合在了一起。
package com.ls.service;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import com.longshine.indigo.dbutils.DBUtils;import com.ls.vo.Spec;public class SpecService {public List<Spec> getDevMainTypeList() {List<Spec> list = new ArrayList<Spec>();String sql = "select distinct asset_main_type_id id,asset_main_type_name name from scgl.t_jx_spec";ResultSet res = DBUtils.executeQuery(sql, null);try {while (res.next()) {Spec spec = new Spec(res.getString("id"),res.getString("name"), "devmaintype");spec.setChildren(new ArrayList<Spec>());list.add(spec);}} catch (SQLException e) {e.printStackTrace();}return list;}public List<Spec> getSpecListByDevMainTypeID(String id) {String sql = "select * from t_jx_spec where asset_main_type_id=?";List<Spec> list = new ArrayList<Spec>();ResultSet res = DBUtils.executeQuery(sql, new Object[] { id });try {while (res.next()) {Spec spec = new Spec(res.getString("id"),res.getString("name"), "spec");spec.setChildren(new ArrayList<Spec>());list.add(spec);}} catch (SQLException e) {e.printStackTrace();}return list;}public List<Spec> getPropListBySpecID(String id) {String sql = "select * from t_jx_prop where spec_id=?";List<Spec> list = new ArrayList<Spec>();ResultSet res = DBUtils.executeQuery(sql, new Object[] { id });try {while (res.next()) {Spec spec = new Spec(res.getString("id"),res.getString("name"), "prop");list.add(spec);}} catch (SQLException e) {e.printStackTrace();}return list;}}

然后在remote-config.xml中设置服务,这样Java端的工作就已经完成。
<destination id="specService"><properties><source>com.ls.service.SpecService</source></properties></destination>

Client端(Flex4)
首先在Flex中构建一个与Java端Spec对象相映射的VO类——SpecVO。
package vo{import mx.collections.ArrayCollection;[RemoteClass(alias="com.ls.vo.Spec")]public class SpecVO{public var id:String;public var name:String;public var type:String;public var children:ArrayCollection;public function SpecVO(){}}}

接下来就是MXML文件,
<?xml version="1.0" encoding="utf-8"?><s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"   xmlns:s="library://ns.adobe.com/flex/spark"   xmlns:mx="library://ns.adobe.com/flex/mx"   minWidth="955" minHeight="600" creationComplete="initApp()"><fx:Script><![CDATA[import mx.collections.ArrayCollection;import mx.controls.Alert;import mx.events.ListEvent;import mx.events.TreeEvent;import mx.rpc.events.FaultEvent;import mx.rpc.events.ResultEvent;import vo.SpecVO;[Bindable][ArrayElementType("vo.SpecVO")]private var treeData:ArrayCollection=new ArrayCollection();[Bindable]private var selectedNode:SpecVO;protected function initApp():void{remoteService.getDevMainTypeList();}protected function remoteService_faultHandler(event:FaultEvent):void{Alert.show(event.fault.message);}protected function getDevMainTypeList_resultHandler(event:ResultEvent):void{treeData=event.result as ArrayCollection;}protected function getSpecListByDevMainTypeID_resultHandler(event:ResultEvent):void{selectedNode.children=event.result as ArrayCollection; treeData.itemUpdated(selectedNode);}protected function getPropListBySpecID_resultHandler(event:ResultEvent):void{selectedNode.children=event.result as ArrayCollection;treeData.itemUpdated(selectedNode);}protected function specTree_itemOpeningHandler(event:TreeEvent):void{selectedNode=event.item as SpecVO;if(!specTree.isItemOpen(event.item)&&selectedNode.children.length==0){if(selectedNode.type=="devmaintype")remoteService.getSpecListByDevMainTypeID(selectedNode.id);else if(selectedNode.type=='spec')remoteService.getPropListBySpecID(selectedNode.id);}}]]></fx:Script><fx:Declarations><!-- 将非可视元素(例如服务、值对象)放在此处 --><s:RemoteObject id="remoteService" destination="specService"fault="remoteService_faultHandler(event)"><s:method name="getDevMainTypeList" result="getDevMainTypeList_resultHandler(event)"/><s:method name="getSpecListByDevMainTypeID"  result="getSpecListByDevMainTypeID_resultHandler(event)"/><s:method name="getPropListBySpecID" result="getPropListBySpecID_resultHandler(event)"/></s:RemoteObject></fx:Declarations><s:Panel width="75%" height="75%" horizontalCenter="0" title="Halo Tree Control Example" verticalCenter="0"><s:VGroup left="10" right="10" top="10" bottom="10"><s:Label width="100%" color="blue" text="Select a node in the Tree control."/><mx:HDividedBox width="100%" height="100%"><mx:Tree id="specTree" width="50%" height="100%" dataProvider="{treeData}" itemOpening="specTree_itemOpeningHandler(event)" labelField="name" showRoot="true"></mx:Tree><s:TextArea width="50%" height="100%" text="Selected Item:"/></mx:HDividedBox></s:VGroup></s:Panel></s:Application>

程序初始化时调用RemoteService来加载第一级节点,点击节点时会首先判断节点是否第一次展开,如果是则根据SpecVO的type字段来选择方法去后台获取子节点。resultHandler中将获取的ArrayCollection赋值给节点的children字段,然后使用ArrayCollection的itemUpdate()方法更新数据源。此方法若没有则Tree无法马上渲染子节点。
启动Tomcat,运行Flex页面测试如下:



到此基本实现了Flex的Tree的延迟动态加载,至于之后的增删改就容易多了。希望通过后期的了解和学习能有更合适的解决方案。

热点排行