Google analytics code

Tuesday, April 13, 2010

Flex / ActionScript: Copy an ArrayCollection

While working with an ArrayCollection I ran into a issue. It seems when you set one ArrayCollection equal to another they share memory space. This can cause issues when you perform any operation that will alter the internal array.

var arrayCollection1:ArrayCollection = new ArrayCollection([1,2,3,4,5]);
var arrayCollection2:ArrayCollection = arrayCollection1;

trace("arrayCollction1: " + arrayCollection1.toString());
trace("arrayCollction2: " + arrayCollection2.toString());

arrayCollection1.removeItemAt(0);

trace("arrayCollction1: " + arrayCollection1.toString());
trace("arrayCollction2: " + arrayCollection2.toString());
Output:
arrayCollection1: 1,2,3,4,5
arrayCollection2: 1,2,3,4,5

arrayCollection1: 2,3,4,5
arrayCollection2: 2,3,4,5

The simple solution for this is to always create a new ArrayCollection for the target using the toArray method from the source.

var arrayCollection1:ArrayCollection = new ArrayCollection([1,2,3,4,5]);
var arrayCollection2:ArrayCollection = new ArrayCollection(arrayCollection1.toArray());

trace("arrayCollection1: " + arrayCollection1.toString());
trace("arrayCollection2: " + arrayCollection2.toString());

arrayCollection1.removeItemAt(0);

trace("arrayCollection1: " + arrayCollection1.toString());
trace("arrayCollection2: " + arrayCollection2.toString());
Output: 
arrayCollection1: 1,2,3,4,5
arrayCollection2: 1,2,3,4,5

arrayCollection1: 2,3,4,5
arrayCollection2: 1,2,3,4,5

Those post is based on findings from this blog post.

7 comments:

  1. If you have an array of objects (not a primitive types you have in example) this approach may fail. You'll need to deep copy the array by using the ByteArray:


    import flash.utils.ByteArray;

    function clone(source:Object):*
    {
    var myBA:ByteArray = new ByteArray();
    myBA.writeObject(source);
    myBA.position = 0;
    return(myBA.readObject());
    }

    For more details see:

    http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7ee7.html

    ReplyDelete
  2. You can still simplify it more :

    var overkill: ArrayCollection = ObjectUtil.copy(source) as ArrayCollection;

    :-)

    ReplyDelete
  3. @Mediocre-Ninja.blogSpot.com Thanks for the tip. That worked like a champ.

    ReplyDelete
  4. that's mainly because arrayCollection1 and arrayCollection2 are pointers. Every time when you set object1 = object2, they will share the same memory, because you give them the same address to look at.

    ReplyDelete
  5. hey my issue is simple
    my arraycollection is made of nested objects and after clone or copying i want to retain the type.

    neither ObjectUtil.copy nor the byte array converstion method works in this scenario.

    Finally i think i will be creating a recursive function to do it but alas this will not be very Generic

    ReplyDelete
  6. @ChaBS: take a look at the [RemoteClass] metadata tag. Need to mark classes that should preserve type information on ByteArray.writeObject() / readObject()

    ReplyDelete
  7. ChaBS

    Type is lost while using copy() if your value object is not having remote tag. This is due to the reason that core AMF serialization is used for deep copy. In case you do not have remote tag you need to use registerClassAlias() to register you value object first. Then using copy() will retain the type. You can check:
    http://www.flex4java.blogspot.in/2013/02/problem-with-objectutil-copy.html

    ReplyDelete

If you found this page useful, or you have any feedback, please leave a comment.