如何在actionscript中复制传输对象的ArrayCollection?

时间:2011-10-27 15:18:10

标签: actionscript-3 flex4

public function create():ArrayCollection{

            var index:int = 0;
            var data:ArrayCollection = new ArrayCollection();
            var length:int = originalData.length;

            for(index; index < length; index++){
                data.addItem(originalData[index]);
            } 

            return data;
        }
  • originalData是数据库中数据的原始状态。
  • data是原始数据的副本,曾经作为我的List组件的提供者进行操作。
  • 我用一个按钮来调用上面的create()函数 意思是,我想恢复数据的所有变化,然后再回过头来 我在originalData中拥有的一切。

但是当我调试我的函数时,originalData会对数据进行所有更改。

当我使用

list.selectedItem.thing =“new string”;

应该修改数据[index] .thing,因为数据是我的List.dataprovider。但它改变了原始数据[索引]。还有这个集合,除了创建自己的副本外,没有用于任何东西!

我不知道为什么会这样。我不知道如何将此行为称为谷歌查询。

如果您不理解这个问题,请注释,以便我可以尝试使其更清晰。这比其功能值得花费更多的时间。

编辑:

我也试过这个,但它不起作用:

public function create():ArrayCollection{

            var index:int = 0;
            var data:ArrayCollection = new ArrayCollection();
            var length:int = originalData.length;

            for(index; index < length; index++){
// initializing a Item object.
                var dataItem:Item = new Item();
                dataItem = originalData[index] as Item;
                data.addItem(dataItem);
            } 

            return data;
        }

编辑2:

根据你的答案和一些研究,我想出了这个通用函数来复制由自定义对象组成的arrayCollections。

public static function copy(objectClassName:String, objectClass:Class, arrayCollection:ArrayCollection):ArrayCollection{
            var index:int = 0;
            var length:int = arrayCollection.length;
            var copy:ArrayCollection = new ArrayCollection();

            for(index; index < length; index++){
                registerClassAlias(objectClassName,objectClass);
                copy.addItemAt(ObjectUtil.copy(arrayCollection.getItemAt(index)) as objectClass,index);
            }
            return copy;
        }

4 个答案:

答案 0 :(得分:4)

正如汤姆所说,这是因为AS3通过引用传递。如果您不想修改原始值,那么您应该再次像Tom所说的那样创建它们的副本。

幸运的是,AS3有一个实用程序 - ObjectUtils.copy。请尝试使用此代码而不是原始代码:

public function create():ArrayCollection{

            var index:int = 0;
            var data:ArrayCollection = new ArrayCollection();
            var length:int = originalData.length;

            for(index; index < length; index++){
                data.addItem(mx.utils.ObjectUtil.copy(originalData[index]));
            } 

            return data;
        }

请注意copy()返回一个通用Object。如果要以类型安全的方式访问其任何属性,则必须将其强制转换为其类型。

更多关于传递参考交易的信息。假设我们在内存中有浮动的项目a,b和c。你把它们放入一个数组(originalData)。 originalData现在包含引用到a,b和c。然后创建一个ArrayCollection并插入(再次)对a,b,c的引用。对象a,b和c不是存储在数组或ArrayCollection中的对象。因此,当您更新originalData [0]时,您将获得对象(a)的引用,并进行更新。

同样,当您更新ArrayCollection.getItemAt(0)时,您将获得相同的引用并更新基础对象,这就是您获得行为的原因。制作副本并插入它意味着您引用了一个全新的对象。

答案 1 :(得分:0)

我不习惯动作脚本,但它看起来像是在将对象从一个arrayCollection引用到另一个arrayCollection。因此,如果您更改这些对象,这将反映在两个arrayCollections中,因为它们引用相同的对象。

为避免这种情况,您应该从原始对象复制以放入新的arrayCollection。

答案 2 :(得分:0)

要创建数组的深层副本并保留类型,请使用以下方法:

public static function clone(source:Object):* 
{ 
    var myBA:ByteArray = new ByteArray(); 
    myBA.writeObject(source); 
    myBA.position = 0; 

    return(myBA.readObject()); 
}

这是Adobe提出的方式。

更新:类型安全复制功能的想法

public static function copyTypeSafe( ac:ArrayCollection ):ArrayCollection
{
    var cloneAc:ArrayCollection = new ArrayCollection();

    if( ac.length ==  0 ) {
        return cloneAc;
    }

    var className:String = getQualifiedClassName( ac.getItemAt(0) );
    registerClassAlias( className, (getDefinitionByName( className ) as Class ) );

    for each (var obj:Object in ac) 
    {
        cloneAc.addItem( ObjectUtil.copy( obj ) );
    }

    return cloneAc;

}

答案 3 :(得分:0)

您需要对集合中的每个类执行registerClassAlias调用,然后只使用上面建议的ByteArray函数clone,它将正常工作。关键是对要维护的ArrayCollection中的每个类型执行registerClassAlias调用。就我而言:

var productGroupClassName:String = getQualifiedClassName(ProductGroup);
                registerClassAlias( productGroupClassName, ProductGroup );
                var productClassName:String = getQualifiedClassName(Product);
                registerClassAlias( productClassName, Product );
                //Need to create a copy so the original values will not be altered
                dataProvider = copyTypeSafe(EnalityData.productsInfo);