对一个集合排序,经常用到类似下面的代码片段:
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