1

I'm writing an app now which uses four main buttons that take up most of the screen. Each one has three animations: a 12 frame introductory animation, a 33 frame looping animation, and an animation that closes based on the current frame the loop was clicked.

Images around around 250 250 to 450 250 in height. Loading all of these as the app loads has turned out to not only cause slow initial loading, but also has resulted in Out of Memory Exceptions on devices with smaller available memory.

The problem is that when I try to load the animations without preloading them, it skips and hangs for a second before loading it. Also, I noticed that even while just running active animations when they are needed per click listeners, memory usage seems to go from between 20mb to 40mb heap size.

I'm not really doing anything weird implementing them. I use a standard

AnimationDrawable animation = (AnimationDrawable)getResources().getDrawable(R.drawable.blah);
imageView.setImageDrawable(animation);
animation start;

But then loading individual animations as needed without preloading makes a slight delay. Is there a way to pre preload them (if that makes any sense) or do something else in terms of how I'm implementing them in code? I'm currently working on chopping the animations into different parts so the only frames changing are the actual parts of the object that are animated.

Other than that, how else can I deal with AnimationDrawable and memory? It seems like Animation is so fundamental to Android, there must be better, professional ways of handling animated resources so they don't break the memory bank and are still fluid. Please let me know I'm doing this the stupid way. Should I be using a different animation class, or perhaps manually assigning changed to an animated view based on a timer so I'm loading one at a time?

I guess this is kind of a messy question - it just seems like there's got to be a standard way of handling this kind of problem. Less frames? Different format images? (jpg and png were the same)

Andrew Hawes
  • 48
  • 1
  • 5

2 Answers2

1

You can do couple of things to minimize memory consumption.

  • Re-size the image to exact button size. You do not need bigger image
  • Resize the image to screen resolution. if you screen is small their are no reason you load a larger image.
  • Provide image in various resolution by following android design guideline.
  • Keep most the image fix and only load/change the animated part

Crash Avoidance

  • Check total heap memory size before loading image onto memory link
  • Make sure that garbage collection working. Bitmap garbage collection is little different then regular garbage collection and depend on Android version.
  • Try Java References.
Community
  • 1
  • 1
minhaz
  • 4,233
  • 3
  • 33
  • 49
  • Thanks for the response. In regard to providing exact resources, the reason I'm just resizing everything is because I have a layout of buttons that is designed to be pieced together to reconstruct one image. The entire thing has to be exactly the same as the specific screen width, so providing exactly sized buttons for every screen is not really feasible. The total of all images plus animations is about 2mb. If I provide different resources for various resolutions, will it only include the proper resolution when a user downloads the app? – Andrew Hawes Jun 09 '13 at 06:59
  • I was primarily concerned about increasing the file size of the apk when uploading, but I'm guessing only the proper resources for the device would be downloaded/installed if i provided multiple sets? Also, I noticed that when I provided multiple resolutions and it tried to use the wrong one when testing, heap size went up to 100mb real quick with the same code (using ldpi resources on an hdpi screen). For now, I've had the images cut up so only the small sections that are actually animated will be, as opposed to just animating entire larger buttons. – Andrew Hawes Jun 09 '13 at 07:00
0

You can use DiskLruCache for caching bitmap. It helps you to solve memory issues and also display image with same quality. Refer https://github.com/JakeWharton/DiskLruCache

You have to do caching only one time. After than It loads images from cache folder.

     int count = 0;
         Runnable runnable = new Runnable() {

            @Override
            public void run() {
                count++;
                if (count < TOTAL_IMAGES) {
                   loadBitmap(count);
                   handler.postDelayed(runnable, 0);
            }
        }
    };
    handler.postDelayed(runnable, 0);


  // method for loading bitmap from cache folder
  private void loadBitmap(int id) {
            String filePath = Environment.getExternalStorageDirectory()+ "Folder Name/ Image Name " + id ;
            BitmapFactory.Options options = new BitmapFactory.Options();

            Bitmap b = BitmapFactory.decodeFile(filePath, options);
            if (b != null) {
                img.setImageBitmap(b);
                }
        }
Roshni Kyada
  • 725
  • 1
  • 6
  • 10
  • Thank you! This looks like it will actually help quite a bit. I'll see what I can do with it tomorrow when I work on the app. Would upvote, but my reputation isn't high enough yet. – Andrew Hawes Jun 09 '13 at 07:06