Friday, July 18, 2008

Springtime

Here, finally, is the source code for the Spring effect seen in the video posted on Adobe TV last week. I took my time posting it because I didn't want to spring it on you too suddenly. Or maybe it was the wrong season (not the winter of my discontent, but the summer of my abject laziness). Or more probably, I just had other stuff to do, like code to actually write and check into Flex 4.

But also, tink brought up some good points in the comments to that blog that I wanted to look into and it turns out he was completely correct; there were two problems with my previous version of Spring, as shown in the video. Both are related to memory, although one is more significant than the other.

The first, and most important, issue is that I should have dispose()'d the BitmapData object, in order to release the memory that it had allocated for the bitmap copy of the component. You might think (as I did) that this would be automatically released when its referring objects go away, but that's not the case. Perhaps this is because the BitmapData object can be shared among multiple objects (as in the case of the Bitmap object, which I now use for the sprite), so it's more difficult for the Flash engine to tell when it's not needed anymore.

In any case, you should dispose() a BitmapData object when you no longer need it, particularly in a case like the Spring effect, where we create a new one every time we play the effect. If you bring up TaskManager on Windows, you can see the memory leaking away in nice 64k chunks, which makes sense given that the icons are 128x128, and a bitmap is typically 4 bytes/pixel, so that's 65,536 bytes, or 64k.

Note, however, that you have to wait until you don't need the BitmapData any longer. This is really only the case when the effect ends, as it is used as a source for the drawing while the effect is playing. So the new version of the code declares bmData as an instance variable and calls dispose() in onTweenEnd(), after we're done with it:

        override public function onTweenEnd(value:Object):void
        {
            super.onTweenEnd(value);
            component.stage.removeChild(springer);
            // dispose of the bitmap to release its memory
            bmData.dispose();
        }

The second change issue in the code is much more minor, but could be important in applications that use many more objects than this one. I chose, for no particular reason, to use a Sprite object to hold my bitmap data. But a Sprite is more than I need. All I really want is an object to hold the BitmapData; a Bitmap object is much simpler (both to create and in functionality). So I've changed the code to use that instead of Sprite:

        springer = new Bitmap(bmData, "auto", true);

Check out the source code, or play the demo for yourself:

6 comments:

Steve Good said...

Hey Chet,

This is an awesome demo! I do have one question though. I applied the spring effect to a datagrid, but instead of springing the selected row it springs the whole datagrid. Any tips on how I could get it to spring the current datagrid row?

Thanks!
~Steve

Chet Haase said...

Hey Steve,

Thanks for the idea: see my SpringItem posting on this tweak.

Anonymous said...

Great work!

Thank you for sharing the source code.

Anonymous said...

Very very cool effect! I have to find somewhere to work this into one of my applications!

Nuwan said...

Thank you for the sample Chet,
so is there any other Effect that we can use in Flex, like this Spring Class?

Chet Haase said...

nuwan: There are lots of effects built into Flex itself. The point of this demo was to show how you could build your own custom effect if the standard ones did not serve your needs. But check out effects like Move, Resize, and Fade, along with Parallel and Sequence for combining effects; you can get some pretty cool effects out of Flex just by using the standard framework, no custom effects required.