集合的refresh()方法

对一个集合排序,经常用到类似下面的代码片段:

ArrayCollection(this.dataProvider).addEventListener(CollectionEvent.COLLECTION_CHANGE,onRefresh);
var sort:Sort = new Sort();
sort.fields = [new SortField(this._sortField,false,false,Array.NUMERIC)];
ArrayCollection(this.dataProvider).sort = sort;
_debugString+=(new Date().time+" sortStartTime")+"\n";
trace(ArrayCollection(this.dataProvider).getItemAt(0).a,"AA");
ArrayCollection(this.dataProvider).refresh();
trace(ArrayCollection(this.dataProvider).getItemAt(0).a,"BB");
private function onRefresh(e:CollectionEvent):void
{
	switch(e.kind)
	{
		case "refresh":
			trace("refresh finished!");
break; } }
}
一直以为集合调用refresh()方法后才开始排序,直到ArrayCollection发出CollectionEvent(kind="refresh")事
件后,排序才完成。如是在CollectionEvent事件处理函数中来处理排序后的集合数据...其实这是错误的!! 
其实,在执行refresh()时,是先对数据进行排序后更新视图。至于排序什么时候完成的,没有通知。
当CollectionEvent(kind="refresh")事件发送时,排序肯定完成,且视图也更新完成,它是用来
告诉你视图更新完成而非排序完成。所以上面的输出
  trace(ArrayCollection(this.dataProvider).getItemAt(0).a,"AA");
  是原始集合的第一项,未排序的第一项
  trace(ArrayCollection(this.dataProvider).getItemAt(0).a,"BB");
  是排序后集合的第一项,也是视图更新后视图中的第一项如:list组件的第一项等。
上面的三个trace语句执行顺序应该是:
  1。trace(ArrayCollection(this.dataProvider).getItemAt(0).a,"AA");
  2。trace("refresh finished!");
  3。trace(ArrayCollection(this.dataProvider).getItemAt(0).a,"BB");
不管你的排序集合有多少数据,只要执行排序操作不超过编译器默认时间限制15秒,它都会按照上面的顺序执行。
也许你会认为当排序的数据很多的时候如:1000000时,排序时间会很长,在1执行后会执行3,排序完成执行2?但这个是错误的!
下面有个测试的例子:
MyList.as
package myComponent
{
	import mx.collections.ArrayCollection;
	import mx.collections.Sort;
	import mx.collections.SortField;
	import mx.controls.List;
	import mx.events.CollectionEvent;
	
	public class MyList extends List
	{
		private var _myData:ArrayCollection;
		private var _sortField:String;
		private var _count:int;
		private var _isSort:Boolean;
		
		private var _timeStart:Number;
		private var _maxWidth:int;
		private var _debugString:String;
		
		private var _isMeasure:Boolean;
		private var _isChange:Boolean;
		
		public function MyList()
		{
			_debugString="";
		}
		
		override public function set dataProvider(value:Object):void
		{
			super.dataProvider = value;
			this._isChange=true;
			ArrayCollection(this.dataProvider).addEventListener(CollectionEvent.COLLECTION_CHANGE,onRefresh);
			
		}
		
		override protected function commitProperties():void
		{
			super.commitProperties();
			if(this._isChange)
			{
				if(this.dataProvider is ArrayCollection)
				{
					if(this.dataProvider.length<=0)return;
				 	var sort:Sort = new Sort();
					sort.fields = [new SortField(this._sortField,false,false,Array.NUMERIC)];
					ArrayCollection(this.dataProvider).sort = sort;
					_debugString+=(new Date().time+" sortStartTime")+"\n";
					trace(ArrayCollection(this.dataProvider).getItemAt(0).a,"AA");
					ArrayCollection(this.dataProvider).refresh();
					trace(ArrayCollection(this.dataProvider).getItemAt(0).a,"BB");
					_debugString+="be sorted!!\n";
					_debugString+="====================";
					_count++;
					this._isSort=true;
				}
				this._isChange=false;
			}
			
		}
		
		public function set sortField(value:String):void
		{
			this._sortField = value;
		}
		public function get sortField():String
		{
			return this._sortField;
		}
		
		override protected function measure():void
		{
			super.measure();
			if(!this.dataProvider)return;
			if(this.dataProvider.length<=0)return;
			
			var n:int = this.dataProvider.length;
			if(_isSort)
			{
				for(var i:int = 0;i<n;i++)
				{
					var len:int = this.dataProvider.getItemAt(i)[_sortField].toString().length;
					if(len>_maxWidth)_maxWidth=len;
				}
				trace("Just One!!");
				this.minWidth = _maxWidth*10;
				this.measuredWidth = _maxWidth*10;
				_isSort=false;
			}
		}
		
		private function onRefresh(e:CollectionEvent):void
		{
			switch(e.kind)
			{
				case "refresh":
					_debugString+=(new Date().time+" sortEndTime")+"\n";
					break;
			}
		}
		
		[Bindable]
		public function get debugString():String
		{
			return this._debugString;
		}
		public function set debugString(value:String):void
		{
			
		}
	}
}

主文件:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:myComponent="myComponent.*" creationComplete="init()">
	<mx:Script>
		<![CDATA[
			import mx.events.ListEvent;
			import mx.events.ItemClickEvent;
			import mx.collections.ArrayCollection;
		
			[Embed(source='../.version',mimeType="application/octet-stream")]
			private var ver:Class;
			
			
			private function getRandomStr():String
			{
				var random:int = 1+Math.floor(Math.random()*(30));
				var str:String = "";
				for(var i:int = 0;i<random;i++)
				{
					str+=String.fromCharCode(97+Math.floor(Math.random()*(26)));
				}
				return str;
			}
			
			private function setDp(n:int):ArrayCollection
			{
				var dp:ArrayCollection = new ArrayCollection;
				for(var i:int = 0;i<n;i++)
				{
					var o:Object = {};
					o.a = getRandomStr();
					o.b = Math.floor(Math.random()*1000)+1;
					dp.addItem(o);
				}
				return dp;
			}
			
			
			private function init():void
			{
				VersionUtil.setRightMenu(ver,this,"TestApp Build@build R@release");
				myList.dataProvider = setDp(1000);
				ta.text = myList.debugString;
			}
			
			private function listClick(e:ListEvent):void
			{
				trace(myList.selectedItem.a);
			}
			
			private function sort():void
			{
				var n:int = int(numTi.text);
				myList.dataProvider = setDp(n);
				ta.text = myList.debugString;
			}
			
			
		]]>
	</mx:Script>
	<myComponent:MyList id="myList" labelField="a" sortField="a" x="379" y="10" height="607" itemClick="listClick(event)"/>
	<mx:TextInput x="10" y="11" id="numTi" text="1000"/>
	<mx:Button x="10" y="41" label="sort" id="btn" click="sort()"/>
	<mx:TextArea id="ta" x="10" y="81" text="{myList.debugString}" height="467" width="361"/>
</mx:Application>

最终的测试:demo

posted @ 2010-05-09 23:37  ywxgod  阅读(1891)  评论(0编辑  收藏  举报