Jul 11, 2012

ArrayCollection ‘source’ attribute vs ListCollectionView ‘list’ attribute


     I recently stumbled upon an interesting problem that highlighted the difference between ArrayCollection ‘source’ attribute and the ListCollection ‘list’ attribute. I was working through some code that was not paying close attention to how it re-wrapped collection data. In some cases a collection was created to wrap the ‘source’ of another collection as in Figure 1. In other cases a new collection was created to wrap the ‘list’ of the original collection as in Figure 2. The code was wrapping the data in new ArrayCollections in order to apply different sorting and filtering, which is an extremely common use for collection views, but was stumbling upon some interesting runtime results… Not all of the collection views were updating with the collection changes.

var ac1:ArrayCollection = new ArrayCollection();
var ac2:ArrayCollection = new ArrayCollection(ac1.source);
Figure 1 – Clone ArrayCollection using the ‘source’ attribute

var ac1:ArrayCollection = new ArrayCollection();
var ac2:ArrayCollection = new ArrayCollection();
ac2.list = ac1.list;
Figure 2 – Clone ArrayCollection using the ‘list’ attribute

How ‘source’ and ‘list’ relate and why it matters

     Jumping into the Flex SDK source code the setter method ArrayCollection.source creates a new ArrayList around the original source to create the ‘list’ attribute of the new collection view. What this means is that depending on how your new collection view wraps the original data, you may end up with the same source, but different lists (See figure 3 below).

Blog - ArrayCollection  list vs source

Figure 3 – Possible relationships in related ArrayCollections

     The implications of whether two list collection views share the same ‘list’ vs ‘source’ attribute is significant. The IList ‘list’ attribute dispatches collection events, where as the Array ‘source’ attribute does not. See the unit tests below to see the differences in behavior between these two cases. Both test collections will always contain the same data, but they won’t always be alerted to the collection changes.

/**
* Unit test shows how collection events are NOT shared between two
* collections that share the same 'source' attribute. Both test
* collections will always contain the same data, but changes to the
* data will not alert both collections.
*/

[Test]
public function testChangeToSourceOnlyAlertsSingleWrappedCollectionViews():void
{
//Two array collections, both sharing the same 'source' value
var ac1:ArrayCollection = new ArrayCollection();
var ac2:ArrayCollection = new ArrayCollection(ac1.source);
var addObj:Object = new Object();

//Test code that counts collection events
this.listenAndCountCollectionEvent(ac1);
this.listenAndCountCollectionEvent(ac2);


//TEST - Add sample object to the first ArrayCollection
ac1.addItem(addObj);

//Notice only 1 collection received add event
Assert.assertEquals(1, this.getAddCollectionEventCount(ac1));
Assert.assertEquals(0, this.getAddCollectionEventCount(ac2));

//Reset the collection data and test listeners
ac1.removeAll();
this.listenAndCountCollectionEvent(ac1);
this.listenAndCountCollectionEvent(ac2);

//TEST - Add sample object to the 'source' attribute
ac1.source.push(addObj);
//Notice 0 collections received add event (arrays don't dispatch events)
Assert.assertEquals(0, this.getAddCollectionEventCount(ac1));
Assert.assertEquals(0, this.getAddCollectionEventCount(ac2));

//Reset the collection data and test listeners
ac1.removeAll();
this.listenAndCountCollectionEvent(ac1);
this.listenAndCountCollectionEvent(ac2);

//TEST - Add sample object to the 'list' attribute (remember these
//collections don't share the same list).
ac1.list.addItem(addObj);
Assert.assertEquals(1, this.getAddCollectionEventCount(ac1));
Assert.assertEquals(0, this.getAddCollectionEventCount(ac2));


//Reset the collection data and test listeners
ac1.removeAll();
this.listenAndCountCollectionEvent(ac1);
this.listenAndCountCollectionEvent(ac2);

//TEST – Direct event will update 1 wrapped list collection
ac1.list.dispatchEvent(new CollectionEvent(CollectionEvent.COLLECTION_CHANGE,
false, false, CollectionEventKind.ADD, 0, 0, new Array(addObj)));

//Notice only 1 collection received add event
Assert.assertEquals(1, this.getAddCollectionEventCount(ac1));
Assert.assertEquals(0, this.getAddCollectionEventCount(ac2));
}

Figure 4 – Two collection sharing a ‘source’ attribute

/**
* Test shows that ArrayCollections that share the same 'list'
* attribute will stay in synch with regard to collection events.
**/

[Test]
public function testChangeToListAlertsWrappedCollectionViews():void
{
//Two array collections, both sharing the same 'list' value
var ac1:ArrayCollection = new ArrayCollection();
var ac2:ArrayCollection = new ArrayCollection();
ac2.list = ac1.list;

var addObj:Object = new Object();

this.listenAndCountCollectionEvent(ac1);
this.listenAndCountCollectionEvent(ac2);

//TEST - Adding an object to ac1 also alerts ac2.
ac1.addItem(addObj);
Assert.assertEquals(1, this.getAddCollectionEventCount(ac1));
Assert.assertEquals(1, this.getAddCollectionEventCount(ac2));

//Reset the collection data and test listeners
ac1.removeAll();
this.listenAndCountCollectionEvent(ac1);
this.listenAndCountCollectionEvent(ac2);

//TEST - Add sample object to the 'source' attribute.
//notice array changes don't notify anyone.
ac1.source.push(addObj);
Assert.assertEquals(0, this.getAddCollectionEventCount(ac1));
Assert.assertEquals(0, this.getAddCollectionEventCount(ac2));

//Reset the collection data and test listeners
ac1.removeAll();
this.listenAndCountCollectionEvent(ac1);
this.listenAndCountCollectionEvent(ac2);

//TEST - Updating the list will update the wrapped list collection
ac1.list.dispatchEvent(new CollectionEvent(CollectionEvent.COLLECTION_CHANGE,
false, false, CollectionEventKind.ADD, 0, 0, new Array(addObj)));
Assert.assertEquals(1, this.getAddCollectionEventCount(ac1));
Assert.assertEquals(1, this.getAddCollectionEventCount(ac2));
}

Figure 5 - Two collection sharing a ‘list’ attribute

Summary

     In a nut shell, if two collections share the same ‘list’ attribute, they will dispatch the same collection events. If two collections only share the same ‘source’ attribute they will not. Be careful how you re-wrap collection data as it can leave you scratching your head at run time.

15 comments:

Hua Cai said...

mulberry handbags
tory burch outlet online
tiffany jewelry
swarovski crystal
mulberry outlet
true religion uk
tiffany and co jewelry
prada outlet online
burberry outlet store
adidas trainers
nike air max
longchamp handbags
beats by dr dre
kobe shoes
nike air max 90
ferragamo outlet
true religion jeans
oakley sunglasses
ray ban sunglasses
camisetas futbol baratas
basketball shoes,basketball sneakers,lebron james shoes,sports shoes,kobe bryant shoes,kobe sneakers,nike basketball shoes,running shoes,mens sport shoes,nike shoes
timberland boots
michael kors handbags
mulberry handbags sale
tiffany jewelry
true religion sale
michael kors online outlet
christian louboutin outlet
true religion outlet
true religion jeans outlet
true religion jeans
air jordan shoes
christian louboutin online
jordan pas cher
michael kors uk outlet
20160528caihuali

xumeiqing said...

20160620meiqing
omega seamaster
cheap jordan shoes
tiffany and co
gucci outlet
ralph lauren outlet
rolex submariner
true religion
michael kors outlet
michael kors outlet clearance
fitflops
nike store
longchamp handbag
nike air max
converse uk
louis vuitton outlet
polo outlet
jimmy choo outlet
adidas supercolor
ed hardy uk
oakley sunglasses
nike air max
instyler max
jordan shoes
nike air force white
ray ban outlet
louis vuitton outlet
kobe shoes
toms
michael kors outlet
prada outlet store
adidas stan smith
ralph lauren outlet
fitflop uk
true religion outlet
adidas trainers
cheap nba jerseys
nfl jerseys wholesale
louis vuitton factory outlet

xjd7410@gmail.com said...

kate spade
nike air max 90
louboutin shoes
tod's shoes
louis vuitton handbags
true religion jeans
retro jordans 13
oakley sunglasses
coach outlet store online
gucci handbags
cheap oakley sunglasses
nike roshe run women
gucci outlet online
burberry bags
michael kors outlet
marc jacobs handbags
louis vuitton outlet
coach factory outlet online
nike free run
coach outlet store online clearances
coach factory outlet
kate spade handbags
oakley outlet
oakley sunglasses
coach outlet store online
michael kors outlet
oakley sunglasses
adidas nmd
adidas yeezy
louis vuitton outlet
chenyingying712

dong dong23 said...

san antonio spurs jerseys
christian louboutin sale
air jordan pas cher
burberry outlet
moncler pas cher
ugg sale
louis vuitton
michael kors outlet
sac longchamp
jordan shoes
201610.6wengdongdong

raybanoutlet001 said...

michael kors handbags
oakley sunglasses
pandora jewelry
pandora outlet
cheap michael kors handbags
christian louboutin shoes
michael kors outlet
nike air huarache
lebron james shoes
versace

raybanoutlet001 said...

michael kors handbags
moncler outlet
michael kors outlet clearance
nike tn
golden state warriors
dolce and gabbana
pandora outlet
chicago bears jerseys
louis vuitton pas cher
jordan shoes

dada24 Xu said...

kate spade outlet
michael kors outlet canada
timberland shoes
abercrombie
christian louboutin shoes
chaussure louboutin
cheap jordan shoes
true religion jeans outlet
polo ralph lauren outlet online
nike air huarache
zhi20161209

dong dong23 said...

gucci outlet
ralph lauren outlet
moncler uk
coach outlet store online
ralph lauren outlet
beats by dre
michael kors outlet
ugg boots
ralph lauren uk
seattle seahawks jerseys
201612.27wengdongdong

obat aborsi said...

This blog is so nice to me. I will continue to come here again and again. Visit my link as well. Good luck
cara menggugurkan kandungan

Meiqing Xu said...

birkenstocks
levis outlet online
louis vuitton handbags
coach factory outlet
true religion
fitflops
red bottoms shoes
christian louboutin shoes
fake rolex
toms outlet
20170209CAIYAN

LCc 03 said...

kobe 11
lacoste online shop
links of london outlet store
cheap jordans
yeezy boost
lacoste polo shirts
michael kors handbags
falcons jersey
kobe bryant shoes
kobe 9

John said...

longchamp handbags
gucci borse
mbt
adidas
red bottom
adidas yeezy boost
yeezy boost 350 v2
cheap nike sneakers
oakley vault
ralph lauren sale clearance uk
20170707yuanyuan

adidas nmd said...

ugg boots
browns jerseys
michael kors outlet
mont blanc outlet
michael kors purses
nike outlet
nike outlet
coach outlet
cheap ugg boots
new york knicks jersey

aaa kitty20101122 said...

cheap jordans
michael jordan shoes
true religion outlet
adidas ultra boost uncaged
michael kors
longchamp bags
michael kors handbags
yeezys
harden shoes
adidas stan smith

gondes ribut said...

Use this article to increase your knowledge . cara menggugurkan kandungan