Flex tree xml数据lazy loading

阅读更多

在技术上,这其实没什么纠结的,只是上一个功能关于动态grid弄好已经接近18:00,这临近下班的时间再搞这个问题,而且紧急,在感情还是上蛮纠结的。加上系统本来已经就有个tree在运转,当然数据格式不是基于XML的,只不过那个tree实在太臃肿而且问题不断,现在要重写就更纠结了。

还好我之前在另一个模块写过一个基于XML数据的Tree,代码还算简洁,复用度蛮高,只不过那个场景下不是Lazy Loading,现在要改成Lazy  Loading而已。连写带调半个小时搞定,呵呵。

首先,上次树的定义可以复用,ABCTree.mxml(为避免×××嫌疑,名字以ABC代替):



	
	    [Event(name="treeLoaded", type="flash.events.Event")]
	

 

其次,上次的TreeRadioItemRenderer类也可以复用,只需继承重写两个方法即可满足当前不同业务。TreeRadioItemRenderer.as如下:

public class TreeRadioItemRenderer extends TreeItemRenderer   
{   
public function TreeRadioItemRenderer(){   
    super();   
}     
   
protected var radioButton:RadioButton;     

override protected function createChildren():void{      
     super.createChildren();      
     radioButton = new RadioButton(); 
     radioButton.selected = false;     
     addChild( radioButton );     
     radioButton.addEventListener(Event.CHANGE, changeHandler);      
}   
 
 /**  
   * update dataProvider when user click CheckBox
   */           
 protected function changeHandler( event:Event ):void  {  
	//Set Value Here for your Model
 }   
       
 /**  
   * Initial data when component initialization
   */           
override protected function commitProperties():void{
super.commitProperties();
if (null != data) {
    var s:int = int(data.selected);
    var selected:Boolean = s > 0 ? true : false;
    radioButton.selected = selected;
} else {
    radioButton.selected = false;
}
  }   
     
 /**  
   * reset itemRenderer's width
   */           
  override protected function measure():void{      
     super.measure();      
      measuredWidth += radioButton.getExplicitOrMeasuredWidth();      
  }      
      
 /**  
   * re-assign layout for tree, move lable to right
   * @param unscaledWidth  
   * @param unscaledHeight  
   */           
  override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{      
     super.updateDisplayList(unscaledWidth, unscaledHeight);      
      var startx:Number = data ? TreeListData( listData ).indent : 0;      
           
     if (disclosureIcon)      
      {      
          disclosureIcon.x = startx;      
          startx = disclosureIcon.x + disclosureIcon.width;      
          disclosureIcon.setActualSize(disclosureIcon.width,      
                                       disclosureIcon.height);      
          disclosureIcon.visible = data ?      
                                   TreeListData( listData ).hasChildren :      
                                  false;      
      }      
     if (icon)      
      {      
          icon.x = startx;      
          startx = icon.x + icon.measuredWidth;      
          icon.setActualSize(icon.measuredWidth, icon.measuredHeight);      
      }      
           
      radioButton.move(startx, ( unscaledHeight - radioButton.height ) / 2 );      
      label.x = startx + radioButton.getExplicitOrMeasuredWidth();      
  }   
} 

 继承后的ABCTreeRenderer.as:

public class ABCTreeRenderer extends TreeRadioItemRenderer
{
public function ABCTreeRenderer()
{
	super();
}

public var itemXml: XML;
//用来记录选择的Node的值
override protected function changeHandler( event: Event ):void  
 {  
      ABCTree.selectedXmlNode = itemXml;
 }   

override public function set data(value:Object):void{
if(value != null){
    super.data = value;
    this.itemXml = XML(value);
    if(this.itemXml.@id == "1000" ){
        super.radioButton.visible = false;
    }else
        super.radioButton.visible = true;
	}
}

override protected function commitProperties():void  
{
	super.commitProperties();
	if(ABCTree.selectedXmlNode != null) {
		if(ABCTree.selectedXmlNode.@id == data.@id)
		{
			radioButton.selected = true;
		}else {
			radioButton.selected = false;
		}
	}
}  
}

 这样我可以完整的实现树了:

 页面初始化方法:

private function init():void{
   needLoad = false;
   model.abcTreeData = XML("");
   proTree.dispatchEvent(new Event("treeLoaded"));
}

public function initLoad():void{
				if(needLoad)
					init();
}

 树加载完以后,利用afterInit事件加载第一层数据:

private function afterInit():void{
Mask.show("loadABCTree", "Loading tree data...");
var deg:BusDelegate = new BusDelegate();
deg.getABCTreeNode(model.abcTreeData.@id,classificationsLoaded, loadFailed);
}

//当load完第一层触发
private function classificationsLoaded(event:ResultEvent):void{
   try{
	var str:String = exceptionProcess(String(event.result));
	if(str != "error"){
			var ch:XMLList = new XMLList(str);
			model.abcTreeData.appendChild(ch);
	                         }
       }catch(e){
	needLoad = true;
      }finally{
	     Mask.close("loadABCTree");
  }
}

//Load Tree Data 有异常
private function loadFailed(event:FaultEvent):void {
         needLoad = true;
         Mask.close("loadABCTree");
        if(event.fault.rootCause is ChannelEvent && event.fault.faultString == 'Channel disconnected'){			
	//channel will handle this fault	
      }else if(event.fault.rootCause is ChannelFaultEvent && event.fault.faultString == 'error'){
	channel will handle this fault				
    }else{
	if(event.fault.faultString != null && event.fault.faultString.indexOf("RemoteAccessException") >= 0)
	   Alert.show("Exception occurred, may ABC remote service not ready.");
	else
	    Alert.show("Exception:" + event.fault.faultString);
  }
}

//处理后台返回回来是exception数据还是正常的数据,空也算exception
private function exceptionProcess(str:String): String{
       var respObj:Object = JSON.decode(str);
       var respStatus: String = respObj.respStatus;
       if (respStatus == "failed") {
	var errorMessages: String = respObj.errorMessages;
	if(errorMessages.lastIndexOf(":")!=-1)
	errorMessages=errorMessages.substring(errorMessages.lastIndexOf(":")+1,errorMessages.length);
					Alert.show(errorMessages);
					return "error";
       }
	return String(respObj.result);
}

 加载下一层:

private function loadNextLevel():void{
 if( theClickItem != null && theClickItem.children().length() == 0 ){
   Mask.show("loadABCTree", "Loading tree data...");
   var deg:BusDelegate = new BusDelegate ();
         deg.getAbcTreeNode(theClickItem.@id,nextLeavlLoaded, loadFailed);
				}
}

private function nextLeavlLoaded(event:ResultEvent):void{
				try{
					var str:String = exceptionProcess(String(event.result));
					if(str != "error"){
						var ch:XMLList = new XMLList(str);
						theClickItem.appendChild(ch);
					}
				}catch(e){
		 			needLoad = true;
		 		}finally{
		 			Mask.close("loadABCTree");
		 		}
			}

     最后在onItemOpen(event)事件中来触发loadNextLevel方法:

     var theClickItem:XML = null;

private function onItemOpen(event:TreeEvent):void{
     theClickItem = XML(event.item);
     if( theClickItem.@level == 8 )//值需加载8层
          return;
     loadNextLevel();
}

你可能感兴趣的:(Flex,tree,XML,Data,Lazy,Load)