03.10
An interesting side effect of the way ItemRenderers are used in flex is that rather than creating a new renderer for each line of data, they are reused. That means if you have an EventListener attached to it but then scroll (and thus move the data to a different renderer) you are still listening to the event. So if we have a list of items 1,2,3,4,5) and scroll so that items (3,4,5,6,7) are visible, the listener that was added when item 3 was in the third list item is going to callback when item 5 is on the 3rd slot. Suddenly it feels like your datagrid has a mind of it’s own!
The fix for this is to make sure you clean the item renderer every time the data is assigned. It my current project I was to switch between a searching state and a base state. My data setter looks like this:
override public function set data(value:Object):void { //If we already have data, we need to remove the listeners. Otherwise we're going to get events from the wrong data if (_data) { _data.removeEventListener(SearchStartEvent.TYPE,SearchStart_handler); _data.removeEventListener(SearchResultEvent.TYPE,SearchResult_handler); } //Now we save the data to our internal datastore. This way we can pull the listeners off once we get new data _data = value as MyDataType; _data.addEventListener(SearchStartEvent.TYPE,SearchStart_handler,false,0,true); _data.addEventListener(SearchResultEvent.TYPE,SearchResult_handler,false,0,true); //Since data is assigned as we're scrolling, we don't know the state. The means we have to update the renderer's state if (_data.searching) currentState = "searching"; else currentState = "base"; } |
The side info on this is that you should not put anything in creation that does any kind of logic based on the data because the data will change.
What about removing the EventListener when you are all the way done with the ItemRenderer so that it can be garbage-collected? At what point would you do that?