1

I've heard that using a list of Bitmaps for animation is a bad idea. But I had not run into a situation to prove that was true until now.

The code I have works great. But only on the emulator, or on my phone running Android 6. Anything lower than that and I get an Out of Memory before it finishes initializing.

This is how I'm loading the images in:

public static Image[] flameIs = new Image[300];


for (int i=0;i<300;i++) {
    if (i>=10) framePref="000";
    if (i>=100) framePref="00";
    Assets.flameIs[i] = g.newImage("frames/lighter_" + framePref +i+ ".png", ImageFormat.RGB565);
}

So it's like 300 PNGs, 8bit, about 12k each in size. We're talking about less than 4MB worth of images.

All the app does later is run these frames in a loop forever.

Is there a way to avoid that "out of memory"?

durbnpoisn
  • 4,666
  • 2
  • 16
  • 30

2 Answers2

2

300 Bitmaps of 459x620 loaded as RGB_565 means that you take 300 * 459*620 * 2 = 171 MB of memory.

Looking at https://stackoverflow.com/a/9940415/3413324 which sum up the heap size for popular devices, we can see that your Bitmaps might exceeds the limit even for recent devices.

What you can do is :

  • Reduce the size of your Bitmaps so that they each need less space in memory

  • Reduce the number of Bitmaps you use for your animation, thus reducing the memory footprint

  • Use a GIF that you can load with a library. You can have then direct control of the size of a unique GIF file

  • If possible create your animation programatically
Community
  • 1
  • 1
Gauthier
  • 4,798
  • 5
  • 34
  • 44
  • You get a +1 for now. I will try this. I especially like the list of memory heaps you linked up. I'll get back to this. – durbnpoisn Jan 14 '17 at 13:18
  • I do not know how to go about creating the "animation programatically". This essentially is a single activity running as a frame buffer, that is a constant state of redrawing. Meaning, it's just running in a loop and refreshing the entire screen. This is why I am using an array to hold which frame comes next, etc... – durbnpoisn Jan 14 '17 at 13:22
  • Creating an animation programatically can lead to huge memory gain when your scene is composed of a few set of images that moves around. i.e: an animation that requires only 10 object(Bitmaps) to move around will take less memory if you just have to move them via code than loading each frame of an animation. Though not always possible, it's always good to have it in mind – Gauthier Jan 14 '17 at 13:28
  • I accepted this answer because your suggestion of reducing the size of the images was the best solution. I cropped all 300 of them to 306x509, which literally dropped the heap allocation in half. The app is now supported as far back as Android 4.4. – durbnpoisn Jan 15 '17 at 13:34
0

Instead of creating a 300 frame animation, why not just convert them into a GIF and use something like Glide to render it? (or even a webview if you don't want to add a new library to your project)

It'll give you better control and portability across platforms.

With Glide, it will look something like this:

ImageView imageView = (ImageView) findViewById(R.id.imageView); GlideDrawableImageViewTarget imageViewTarget = new GlideDrawableImageViewTarget(imageView); Glide.with(this).load(R.raw.sample_gif).into(imageViewTarget);

  • If this program were written as an Activity using XML this would be an option. But the way it's currently written, it redraws the page constantly. Meaning, that the GIF would not persist. It's a good idea for next time, though. – durbnpoisn Jan 14 '17 at 14:11