Is there a way to clean up embedded Bitmap resources in AS3 / AIR

first publication here.

I am creating an AIR 3.0 application.

For many of my graphics assets, I use the built-in Flex metadata to insert bitmap objects as classes and then create them.

The problem is, they never seem to collect trash. I haven't found much information online, but I've seen a couple of posts that seem to confirm this.

Anytime one of my classes gets an instance that has these built-in assets, they always create new Bitmaps and BitmapDatas instances, rather than reusing what's already in memory. This is a huge memory problem. And I can't find a way to de-referenciong them or get them to leave memory.

So the only solution I can think of is to just load the graphics from disk and not use the embed tag. But I would rather not do that, seeing as when the application is packaged and installed, all of these graphical assets will be on the end user's machine rather than being contained in the SWF.

Anyoen bump into this? There is a solution? Or an alternative solution than the one I can think of?

Thank! Kyle

+3


source to share


2 answers


Well, I guess this is the expected behavior because a new operator should always create new objects. But these new objects are supposed to be garbage collected, it just won't be an asset class since it's a class.

You can create a cache that acts like a singleton factory. You request your image by specifying an ID, then the cache will either create that image if it doesn't already exist, or just return one instance if it does. It's been a while since the last coded ActionScript, so maybe you should think of this as pseudocode;)

public class Cache {

    import flash.utils.Dictionary;
    import flash.utils.getDefinitionByName;

    [Embed(source="example.gif")]
    public static var ExampleGif:Class;

    /**
     * The single instance of the cache.
     */
    private static var instance:Cache;

    /**
     * Gets the Cache instance.
     *
     * @return
     *     The Cache
     */
    public static function getInstance():Cache {
        if (Cache.instance == null) {
            Cache.instance = new Cache();
        }
        return Cache.instance;
    }

    /**
     * The cached assets are in here.
     */
    private var dictionary:Dictionary

    public function Chache() {
        if (Cache.instance != null) {
            throw new Error("Can not instanciate more than once.");
        }
        this.dictionary = new Dictionary();
    }

    /**
     * Gets the single instantiated asset its name.
     *
     * @param assetName
     *     The name of the variable that was used to store the embeded class
     */
    public function getAsset(assetName:String):Object {
        if (this.dictionary[assetName] == null) {
            var AssetClass = getDefinitionByName(assetName) as Class;
            this.dictionary[assetName] = new AssetClass();
        }
        return this.dicionary[assetName];
    }

}

      



Then you can use it like this:

public class Example {

    public static function main() {
        Bitmap exampleGif1 = Cache.getInstance().getAsset("ExampleGif") as Bitmap;
        Bitmap exampleGif2 = Cache.getInstance().getAsset("ExampleGif") as Bitmap;
        trace("both should be the same instance: " + (exampleGif1 == exampleGif2));
    }

}

      

I have not tested this, so let me know if it works.

+1


source


I think you are looking for dispose () http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/BitmapData.html?#dispose ()



If you decide to go with a caching system, here is a link with some code that's tested http://thanksmister.com/2009/01/29/flex-imagecache-a-cheap-way-to-cache-images/ . The link to another technique using SuperImage is broken, but I managed to find this http://demo.quietlyscheming.com/superImage/app.html .

0


source







All Articles