Clone an (Array)Collection

更新:2008.4.2
用ObjectUtil.copy() 複製物件的byteArray:

var myCloneArrayCollection:ArrayCollection =  ObjectUtil.copy( myArrayCollection )  as ArrayCollection;

或者:

var myCloneAC:ArrayCollection = new ArrayCollection( myArrayCollection.list.toArray() );

也可以, 原因是 IList::toArray(); 其實用了 Array#concat();
而concat()方法做了:
Concatenates the elements specified in the parameters with the elements in an array and creates a new array. If the parameters specify an array, the elements of that array are concatenated.
但是但是!如果用了toArray(), Array裡面的item並沒有被複製!

又到了要複製一份ArrayCollection的時間了, 以往都是用很笨很直觀的手法:

//dummy solution( well, it works )
var bar:ArrayCollection = new ArrayCollection();
for each ( var i:Object in ac ){
bar.addItem( i );
}

如今,有位不願具名的神人說了更美妙優雅的作法!!

// fantastic ! //
var bar:ListCollectionView = new ListCollectionView( ListCollectionView( ac ).list );

一行勝千言, 威力可見一斑, 不要再乖乖地走訪array了~

11 Responses to “Clone an (Array)Collection”

  1. saicn Says:

    hello ,我不知道为什么要用如此的方法来做clone arraycollection,

    我一般使用的方法有
    var bar:ArrayCollection = new ArrayCollection();
    bar.source = ac.source;

    如此,有问题吗?

  2. 小薛 Says:

    依據我測試的結果, ac.source 似乎並沒有將整個list複製一次, 而是回傳了list的參照(reference), 或許你會發現trace的結果並沒有什麼不對, 一旦:

    list.dataProvider = acBySource;
    list.dataProvider = acByList;

    結果就不是一樣的了, 用ListCollectionView的顯示會比較正確。

  3. Ticore Says:

    可以看一下原始碼
    source 本質也是用 list

    public function get source():Array
    {
    if (list && (list is ArrayList))
    {
    return ArrayList(list).source;
    }
    return null;
    }

  4. Ticore Says:

    看過原始碼之後,作了簡單測試
    資料並沒有被複製~~

    import mx.collections.*;

    var ary:Array = [1,2,3];
    var ac:ArrayCollection = new ArrayCollection(ary);
    var lc:ListCollectionView = new ListCollectionView();
    lc.list = new ListCollectionView(ac.list).list;
    trace(ac); // 1,2,3
    trace(lc); // 1,2,3
    ary[0] = 0;
    trace(ac); // 0,2,3
    trace(lc); // 0,2,3

  5. 小薛 Says:

    Hi Ticore,
    這個問題的緣由是我在使用filter function 時遇到的, 我有一個dataprovider需要作filter, 可是又不希望其他有binding該dataprovider的元件也跟著改變, 所以複製了一份data 出來作filtering.

    我是這麼用的:

    var ary:Array = [1,2,3];
    var ac:ArrayCollection = new ArrayCollection(ary);

    var lc:ListCollectionView = new ListCollectionView( ac.list );
    //PS: 用您的寫法也會產生相同結果(如下)
    //Ticore:lc.list = new ListCollectionView(ac.list).list;

    trace(ac); // 1,2,3
    trace(lc); // 1,2,3
    //do filtering…
    ac.filterFunction = ff;
    //refreshing the view
    ac.refresh();

    trace(ac); // (Array)#0
    // [0] 3
    trace(lc); // 1,2,3

    private function ff( item : Object ):Boolean{
    return item>2;
    }

    我不確定記憶體裡到底有無複製的一分, 然而, 在filter+refresh()之時, 此方法就出現他的用處了.

  6. 小薛 Says:

    附註一下,
    在我的customized comp裡頭…有時候
    var foo = new ListCollectionView( ac.source )
    var boo = new ListCollectionView( ac.list )

    myList.dataProvider = lc;
    myList.dataProvider = lc2;

    以上兩者居然會產生不同的繪製結果, 其中, 以 boo 的結果最為正確.
    如果您有更多見解, 願聽其詳 :)

  7. Ticore Says:

    不同的繪製結果?!
    可能要給完整的例子才有辦法研究~~

  8. saicn Says:

    小薛,你好,上面之前讨论的问题

    你所说的应该不是clone collection,而是 reference 一个原始的list或者说Array。

    也就是 AC的 原始的array,你建立了一个ListCollection来reference这个AC的原始 数据,而你的Ac的filter是用来修改AC的表现的。

    而真正意义上的Clone ,还是 要 for each出来 。

  9. 冰山上的播客 » Blog Archive » Flex 常用语句 Says:

    [...] 复制ArrayCollection:(From: http://blog.shiue.net/?p=490) //dummy solution( well, it works ) var bar:ArrayCollection = new ArrayCollection(); for each ( var [...]

  10. Flex 常用语句 - 网络应用与资讯 Says:

    [...] http://blog.shiue.net/?p=490) //dummy solution( well, it works ) var bar:ArrayCollection = new ArrayCollection(); for each ( var [...]

  11. Flex 常用语句 | 对影成三人 Says:

    [...] http://blog.shiue.net/?p=490) //dummy solution( well, it works ) var bar:ArrayCollection = new ArrayCollection(); for each ( var [...]

Leave a Reply