views:

848

answers:

3

I'm not so new to the concepts present on J2ME, but I'm sort of lazy in ways I shouldn't: Lately my app has been loading images into memory as they were candy...

Sprite example = new Sprite(Image.createImage("/images/example.png"), w, h);

and I'm not really sure it's the best way, but it worked fine in my Motorola Z6, until last night, when I tested the app in a old Samsung cellphone and the images wont even load and require several attemps of starting the thread to show up. The screen was left on white, so I realized that it has to be something about Image loading that I'm not doing quite well... Is there anyone who can tell me how to properly make a loading routine in my app?.

+2  A: 

I'm not sure exactly what you are looking for, but the behavior you describe very much sounds like you are experiencing an OutOfMemory exception. Try reducing the dimensions of your images (heap usage is based on dimension) and see if the behavior ceases. This will let you know if it is truly an OutOfMemory issue or something else.

Other tips:

1) Load images largest to smallest. This helps with heap fragmentation and allows the largest heap space for the largest images.
2) Unload (set to null) in reverse order of how you loaded and garbage collect after doing so. Make sure to Thread.yield() after you call the GC.
3) Make sure you only load the images that you need. Unload images from a state that the application is no longer in.
4) Since you are creating sprites you may have multiple sprites for one image. Consider creating an image pool to make sure you only load the image once. Then just point each Sprite object to the image within the pool that it requires. Your example in your question seems like you would more than likely load the same image into memory more than once. That's wasteful and could be part of the OutOfMemory issue.

Fostah
thanks Fostah! really helpful, the image pool thing, I've used it before, but using Java2D in a desktop game, so it wouldn't be a problem to do it again. I still have to polish this a little, I need to know how to structure my app. Lately my app is threadish, I have two canvases, each implementing Runnable, one for the menu and other for the gameplay, am i doin' it rite?
ONi
My J2ME games have always consisted of 1 canvas and multiple game states. Then the run() for the canvas has the update loop. Having multiple Canvas instances really shouldn't be needed considering that the States never exist at the same time. Check out J2ME Game Programming by Martin Wells. It's a great book and will be very useful to you.
Fostah
A: 

Using the Fostah approach of not loading images over and over, I made the following class:

public class ImageLoader {
    private static Hashtable pool = new Hashtable();

    public static Image getSprite(String source){
        if(pool.get(source) != null) return (Image) pool.get(source);
        try {
            Image temp = Image.createImage(source);
            pool.put(source, temp);
            return temp;
        } catch (IOException e){
            System.err.println("Error al cargar la imagen en "+source+": "+e.getMessage());
        }
        return null;
    }
}

So, whenever I need an image I first ask the pool for it, or just load it into the pool.

ONi
+1  A: 

Using a film image(a set of images by a defined dimension in one image) and use logic to pull them out one at a time.

Because they a grouped into one image, you are saving header space per image and thus can reduce the memory used.

This techniques was first used in MIDP 1.0 memory constrained devices.

Fred Grott