Flex 对ArrayCollection的重构

由于项目的需要,对ArrayCollection进行重构,包括如下功能: 

1,排序 
2,moveFirst moveLast moveNext movePre 进行记录导航 和选择某个index的对象 
3,删除,更新,插入,添加记录的功能 
4,过滤 

以下是例子:

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init();">
<mx:Script>
<![CDATA[
import mx.collections.CursorBookmark;
import com.hexagonstar.util.debug.Debug;
import org.app.utils.common.collections.MyArrayCollection;
import com.adobe.serialization.json.JSON;
var arr:Array=[
{a:1,b:1,c:1},
{a:21,b:21,c:21},
{a:12,b:12,c:12},
{a:10,b:10,c:10},
{a:2,b:2,c:2}
];
[Bindable]
var coll:MyArrayCollection = null;
[Bindable]
var scc:String = null;
private function init():void{
coll =new MyArrayCollection(arr);
//var sortArr:Array=[{name:"a"},{name:"b"}];
//coll.sortCollection(sortArr);
src.text= coll.toString();
//dest.text = JSON.encode(coll.currentItem);
scc = coll.toString();
dest.text = scc;
//keywords
coll.keywords=["a"];
}

private function insert():void{
var s:String = src.text;
var o:Object = JSON.decode(s);
coll.insertItem(o);
scc = coll.toString();
dest.text = scc;
}
private function append():void{
var s:String = src.text;
var o:Object = JSON.decode(s);
coll.appendItem(o);
scc = coll.toString();
dest.text = scc;
}
private function moveFirst():void{
var o:Object = coll.moveFirst();
dest.text = JSON.encode(o);
}
private function moveLast():void{
var o:Object = coll.moveLast();
dest.text = JSON.encode(o);
}
private function moveNext():void{
var o:Object = coll.moveNext();
dest.text = JSON.encode(o);
}
private function movePre():void{
var o:Object = coll.movePrevious();
dest.text = JSON.encode(o);
}
private function doClear():void{
dest.text = "";
}
private function doUpd():void{
var o:Object = JSON.decode(src.text);
coll.updateItem(o);
o = coll.currentItem;
dest.text = JSON.encode(o);
}
private function doDel():void{
var o:Object = JSON.decode(src.text);
var flg:Boolean = coll.remove();
Debug.trace("--remove:"+flg);
scc = coll.toString();
dest.text = scc;
}
]]>
</mx:Script>
<mx:TextArea id="src" x="25" y="40" width="267" height="103"/>
<mx:Button x="25" y="10" label="更新" click="doUpd();"/>
<mx:Button x="188" y="10" label="删除" click="doDel();"/>
<mx:Button x="244" y="10" label="排序"/>
<mx:Button x="76" y="10" label="插入" click="insert();"/>
<mx:Button x="132" y="10" label="添加" click="append();"/>
<mx:TextArea id="dest" x="300" y="40" width="333" height="103" editable="false" text="{scc}"/>
<mx:Button x="25" y="299" label="|<" toolTip="第一个" click="moveFirst();"/>
<mx:Button x="125" y="299" label=">>" toolTip="后一个" click="moveNext();"/>
<mx:Button x="73" y="299" label="<<" toolTip="前一个" click="movePre();"/>
<mx:Button x="177" y="299" label=">|" toolTip="最后一个" click="moveLast();"/>
<mx:DataGrid x="25" y="151" width="608" height="143" dataProvider="{coll}">
<mx:columns>
<mx:DataGridColumn headerText="ColumnA" dataField="a"/>
<mx:DataGridColumn headerText="ColumnB" dataField="b"/>
<mx:DataGridColumn headerText="ColumnC" dataField="c"/>
</mx:columns>
</mx:DataGrid>
<mx:Button x="585" y="10" label="清空" toggle="true" click="doClear();"/>
</mx:Application>


/**
* 用法:
* coll=new ArrayCollection(
* [
* {name: "Martin Foo", age: 25}, 
* {name: "Joe Bar", age: 15}, 
* {name: "John Baz", age: 23}
* ]
* );
* coll.addItemAt({name: "James Fez", age: 40}, 0);
*/
package org.app.utils.common.collections
{ 

import flash.events.Event;
import mx.collections.ArrayCollection;
import mx.collections.CursorBookmark;
import mx.collections.IViewCursor;
import mx.collections.Sort;
import mx.collections.SortField;
import mx.events.FlexEvent;
 import mx.logging.ILogger;
import org.app.framework.AppContext;
import org.app.utils.common.MyJSONUtils;
import org.app.utils.log.MyLoggerManager;

public class MyArrayCollection extends ArrayCollection
{

/*排序规则参数*/
public static const RL_NAME:String = "name";//要排序的字段的名称。[String]
public static const RL_CASEINSENSITIVE:String = "caseInsensitive";//Boolean 指定此字段的排序是否应不区分大小写。
public static const RL_DESCENDING:String = "descending";//Boolean 指定此字段是否应按降序排序。
/*事件相关*/
//光标位置更新时的事件
public static const EVENT_CURSOR_UPDATE:String = "event_cursor_update";
/*Object 指定当要进行排序的字段包含数值 (number/int/uint) 
* 或数值的字符串表示形式时,比较运算符是否使用数值比较。*/
public static const RL_NUMERIC:String = "numeric";

private var logger:ILogger = MyLoggerManager.getLogger("MyArrayCollection",AppContext.getInstance().appLogTarget);

/*游标*/
private var _cursor:IViewCursor = null;//当前游标
private var _currentItem:Object = null;//当前游标指向对象
/*如果是JSON对象,那么有keys*/
private var _keys:Array = null;//该数组包含的json properties
private var _keywords:Array = null;//哪些properties是主键,用于判断重复
public function MyArrayCollection(source:Array=null)
{
super(source);
//取得当前的光标对象
this._cursor = this.createCursor();
//注册光标位置更新事件
this._cursor.addEventListener(FlexEvent.CURSOR_UPDATE,fireCursorUpdate,false,0,true);
//給当前光标对象赋值--就会触发cursor update事件
this._cursor.seek(CursorBookmark.CURRENT);
//初始化keys 或者 获取keys
this.fetchKeys();
}


/**
* 当光标位置更新时触发的事件,在这取得当前光标位置的值,
* 其他地方光标移动时不要給 currentItem赋值了。
* @param FlexEvent
* @return
*/
private function fireCursorUpdate(event:FlexEvent):void{
//取得当前的值
this._currentItem = (event.currentTarget as IViewCursor).current;
//防止 moveLast moveFirst抛出多2个事件,只有当前有对象值了,才抛出
var a:String = "不抛出";
if (this._currentItem) {
a="抛出";
this.dispatchEvent(new Event(EVENT_CURSOR_UPDATE));
}
var s:String = MyJSONUtils.encode(this._currentItem);
logger.debug("--触发了 cursor update 事件,当前对象:"+s+"["+a+"]");
}


public function set cursor(cursor:IViewCursor):void{
this._cursor = cursor;
}
public function get cursor():IViewCursor{
return this._cursor;
}
public function set currentItem(o:Object):void{
//替换掉当前对象里面的值
this.updateItem(o);
//this._currentItem = o;
}
public function get currentItem():Object{
return this._currentItem;
}

public function fetchKeys():void{
if(this.length>0){
var o:Object = this.getItemAt(0);
this._keys = MyJSONUtils.fetchKeys(o);
}else{
this._keys = [];
}
}
public function getKeys():Array{
if(this._keys.length<=0){
this.fetchKeys();
}
return this._keys;
}
public function set keywords(k:Array):void{
this._keywords = k;
}
public function get keywords():Array{
return this._keywords;
}



/**
* 检查是否存在某个条件的对象??????
* @param Object json object eg:{name:"xxx_name", age:34 .....}
* @param String 比较类型 采用Sort里面引用的常量
* @return int 存在的个数
* 
* @see mx.collections.Sort
*/
public function checkExist(conditionObj:Object,mode:String=Sort.ANY_INDEX_MODE):int{
var sort:Sort = new Sort();
return sort.findItem(this.source,conditionObj,mode); 
}

/**
* [这个比较 很慢]
* 检查是否存在某个对象,其中keys指根据哪些key进行比较,如果为空,那么根据全部key来比
* @param Object
* @param Array 要比较的key
* @return Boolean true存在
*/
public function isExist(o:Object,keys:Array=null):Boolean{
var key1:Array = keys;
if(key1==null){
key1 = MyJSONUtils.fetchKeys(o);
}
var item1:String = null;
var l:int=key1.length;
for each(var obj:Object in this){
var flg:int = 0;
for(var i:int=0;i<l;i++){
item1=key1[i];
if(o[item1]==obj[item1]){
flg++;
}
}
if(flg==l)return true;
}
return false;
}
/**
* 覆盖该方法,来做重复检查
* @param Object 要比较的对象
* @return Boolean true存在
*/
override public function contains(item:Object):Boolean{
return isExist(item,this._keywords);
}

/**
* 按照一定的规则排序,可以多个字段同时排序:
* -- name : String 要排序的字段的名称。 
* -- caseInsensitive : Boolean 指定此字段的排序是否应不区分大小写。 
* -- descending : Boolean 指定此字段是否应按降序排序。
* -- numeric : Object 指定当要进行排序的字段包含数值 (number/int/uint) 
* 或数值的字符串表示形式时,比较运算符是否使用数值比较。 
* eg:[{name:'age',caseInsensitive:true,descending:false,numeric:null},
* {name:'age',descending:false}...]
* 是个数组,而且 里面是json对象,包含四个元素:name,caseInsensitive,descending,numeric,
* 其中,name是必须的,其他的可选。
* @param Object 类似上面的写
* @return
* @see mx.colloections.SortField
* 
*/
public function sortCollection(conditionObj:Array):void{
var leng:int = conditionObj.length;
var fields:Array = [];
var sortField:SortField = null;
var o:Object=null;

var name:String=null;
var caseInsensitive:Boolean=false;
var descending:Boolean = false;
var numeric:Object = null;
for(var i:int=0;i<leng;i++){
o = conditionObj[i];
sortField = new SortField();
//加入参数
sortField.name=o[MyArrayCollection.RL_NAME];

var tmp:Object = o[MyArrayCollection.RL_CASEINSENSITIVE];
caseInsensitive=tmp==null?false:true;
sortField.caseInsensitive=caseInsensitive;

tmp = o[MyArrayCollection.RL_DESCENDING];
descending=tmp==null?false:true;
sortField.descending=descending;

tmp = o[MyArrayCollection.RL_NUMERIC];
numeric=tmp==null?null:tmp;
sortField.numeric=numeric;
//加入比较器
fields.push(sortField);
}
var sort:Sort = new Sort();
sort.fields=fields;
this.sort = sort;
this.refresh();
}

/**
* 过滤,首先必须知道自己要过滤的集合里面有些什么字段,
* coll = new ArrayCollection([
* {name:"Martin Foo", age:25}, 
* {name:"Joe Bar", age:15}, 
* {name:"John Baz", age:23}, 
* {name:"Matt Baz", age:21}]);
* 那么func:
* private function filterFunc(value:Object):Object { 
   * if(Number(value.age) > 21) { 
    * return true; 
   * }
   * return false; 
*} 
* @param Function 如上
* @return
*/
public function filterCollection(filterFunc:Function):void{
this.filterFunction = filterFunc;
this.refresh();
}




/**
* 取得第一个对象,根据cursorMove 来判断是否移动光标
* @param Boolean 是否移动当前光标
* @return Object 第一个位置的对象
*/
public function firstItem(cursorMove:Boolean=true):Object{
if(cursorMove){
return this.moveFirst();
}
return this.getItemAt(0);
}
/**
* 取得最后一个对象,根据cursorMove 来判断是否移动光标
* @param Boolean 是否移动当前光标
* @return Object 最后一个位置的对象
*/
public function lastItem(cursorMove:Boolean=true):Object{
if(cursorMove){
return this.moveLast();
}
return this.getItemAt(this.length-1);
}
/**
* 在最后位置插入对象,会检查是否存在相同的对象.
* @param Object
* @return Boolean true成功 false失败
*/
public function appendItem(o:Object):Boolean{
//该方法检查每个元素都相同
var exist:Boolean= this.contains(o);
if(!exist){
this.addItem(o);
//当前游标处理
this.moveCursorTo(o);
if(this._currentItem){
return true;
}
}
return false;
}

/**
* 在当前位置插入一个对象
* @param Object 
* @return Boolean
*/
public function insertItem(o:Object):Boolean{
  //该方法检查每个元素都相同
var exist:Boolean= this.contains(o);
if(!exist){
this._cursor.insert(o);
//当前游标处理
this.moveCursorTo(o);
if(this._currentItem){
return true;
}
}
return false;
}




/**
* 删除当前光标指向的对象,并选择下一个对象,如果下一个对象为空,那么选择最后一个
* @return Object 当前被删除的对象
* 
*/
public function remove():Object {
var o:Object=this._cursor.remove();
if (!this._currentItem) {
this._cursor.movePrevious();
}
return o;
}
/**
* 删除指定的对象
* @param Object
* @return Boolean true成功 
*/
public function removeItem(o:Object):Boolean{
this.moveCursorTo(o);
var o:Object = this.remove();
if(o)return true;
return false;
}

/**
* 删除所有数据
*/
override public function removeAll():void{
super.removeAll();
this.source = [];
}



/**
* 更新当前光标指向的对象
* @param Object 新的对象
* @return
*/
public function updateItem(o:Object):void{
var keys:Array = MyJSONUtils.fetchKeys(o);
var l:int = keys.length;
var key:String=null;
for(var i:int=0;i<l;i++){
key = keys[i];
if(this._currentItem[key]){
this._currentItem[key]=o[key];
this.itemUpdated(this._currentItem);//这个会令ui更新
}
}
}


/**
* 把光标移到指定的对象上,
* @param Object 目标对象
* @return Object 当前选择的对象
*/
public function moveCursorTo(o:Object):Object {
//当前游标处理
var index:int=this.getItemIndex(o);
return this.moveCursorByIndex(index);
}
public function moveCursorByIndex(index:int):Object{
if(index < 0 || index >= this.length)return null;
var oldIndex:int = this.getItemIndex(this._currentItem);
var offset:int = 0;
if (oldIndex > index) {
offset = -(oldIndex - index);
} else if (oldIndex < index) {
offset = index - oldIndex;
}
this._cursor.seek(this._cursor.bookmark, offset);
return this._currentItem;
}

/**
* 光标指向第一个位置,返回第一个位置的值 
* @return Object 当前光标位置的对象
*/
public function moveFirst():Object{
//当前游标处理
this._cursor.seek(CursorBookmark.FIRST);
//当前对象设置值
//在cursor update 事件里面处理了
//返回当前对象
return this._currentItem;
}

/**
* 光标指向最后一个位置,返回最后一个位置的值 
* @return Object 当前光标位置的对象
*/
public function moveLast():Object{
//当前游标处理
this._cursor.seek(CursorBookmark.LAST);
//当前对象设置值
//在cursor update 事件里面处理了
//返回当前对象
return this._currentItem;
}

/**
* 光标指向下一个位置,返回光标指向位置的对象
* @return Object 当前光标位置的对象
*/
public function moveNext():Object {
if (!this._cursor.afterLast) {
this._cursor.moveNext();
//this._currentItem = this._cursor.current;
if (!this._currentItem) {
this._cursor.movePrevious();
}
}
return this._currentItem;
}

/**
* 光标指向上一个位置,返回光标指向位置的对象
* @return Object 当前光标位置的对象
*/
public function movePrevious():Object {
if (!this._cursor.beforeFirst) {
this._cursor.movePrevious();
if (!this._currentItem) {
this._cursor.moveNext();
}
}
return this._currentItem;
}


/**
* 把值转成字符串
* @return String 
*/
override public function toString():String{
var s:String = "";
var l:int=this.length;
for(var i:int=0;i<l;i++){
s+=MyJSONUtils.encode(this.getItemAt(i));
}
return s;
  }
}//end class
}//end package


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值