01-25-2011 11:40 PM - edited 01-25-2011 11:42 PM
Strange problem here. I have a list, whose cells have a background provided by an image bundled with my application. Before, I was not using an imageCache and there was a momentary flicker whenever a new cell was drawn, as the image was loaded from the disk. Using imageCache and populating the cache with this image before displaying the list solves this problem, but introduces another - when the user clicks an item in this list, my application transitions to another view by removing the container of the current view from the display list and adding the container of the next view to the display list. When the user returns from this new view to the previous view with the list, the images that provide the background of the cells do not display. Only when the list is scrolled, forcing new cells to be drawn, do the background of cells appear as they should.
I am stumped as to what would cause this. By my thinking, it must be a bug with the ImageCache class, as the UIContainers for my different views are all instance variables of the root class of my application. If my understanding of ActionScript garbage collection is correct, this reference, which will be valid for the life of the application, should prevent the image from being garbage collected. I can think of no other reason why the image would be invalidated due to removing it from the display list, as a reference is still kept. The ImageCache object itself is a class variable of the root class of my application, so it should have a valid reference for the lifetime of the application as well.
Currently I am working around the issue by not removing the UIContainer from the display list and instead setting its visible property to false to hide it. This works fine, but I am curious if there is something I am missing that could cause the behavior I'm observing.
01-26-2011 12:19 AM
If you go back to your previous non-cached scheme, do the images get rendered when you add the list back to the stage? Does a DisplayObject's draw() method always get called when it is added to the stage (I would guess it does but I'm new to AS3)? If for some reason it doesn't, maybe the programmer needs to call it in this case. Just looking around at the methods of List class's ancestors, there is an onAdded() protected method of UIComponent intended for override by the programmer; maybe that is a good place to add any extra coded needed to get components redrawn.
01-26-2011 11:02 AM
When an image is removed from the stage it does something that prevents it from being used again. To solve this subclass Image and override onRemove with a blank function body. This will break whatever memory optimizations Image has, so be careful.
03-08-2011 05:11 AM
03-08-2011 03:15 PM
Check that the correct instances of your image object is being used at the correct row by doing a trace on the object name (someobject.name), if it has one.
Not sure if your problem is the same as what I am getting but I also had objects that I instantiated outside of the CellRenderer but are used within it. The instances do remain but I am finding that as I scroll the instances sometimes jump to different rows. I kept track of which instance should be on what row and was finding that after scrolling up and down, the instances got changed on me and I had to ensure that the row had the proper instance by checking for it in the overridden data setter method.
03-08-2011 03:41 PM
CellRenderers get managed and reused by the parent List, you can't make any assumptions as to where they'll be displayed, however whenever the renderer is to be used the "data" property gets set - so it's always been the case with Renderers (including ItemRenderers in Flex) that when you are given new data you reset the whole Renderer.
This isn't really the same problem though, this was a case of the Image getting removed when the Renderer was removed from the Stage and when the List reappeared on the Stage the Renderers did not get refreshed (the existing Renderers were readded), but the Image was already gone. This involves the extra step of overriding onAdded and re-setting any images from data there.
That is, even if the List only had one item, and therefore one Renderer, with an Image in it, which didn't get recycled, - doing removeChild(list) and a subsequent addChild(list) would cause the list to reappear without the image.