2

I am setting help screens images at 4 different places in my app. The activity code is the following-

@Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.help_list);
 int screenType = getIntent().getIntExtra("screenName", 0);
 ImageView imageView = (ImageView) findViewById(R.id.help_image);
 switch (screenType) {
 case 1:
 imageView.setImageResource(R.drawable.help0);
 break;
 case 2:
 imageView.setImageResource(R.drawable.help1);
 break;
 case 3:
 imageView.setImageResource(R.drawable.help2);
 break;
 case 4:
 imageView.setImageResource(R.drawable.help3);
 break;
 }
 findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 finish();
 }
 });

This code executes successfully on most of the devices, but on some devices (for e.g. Samsung), the app crashes with out of memory exception.

I've tried to recycle the Bitmap-

 BitmapDrawable bitmapDrawable = ((BitmapDrawable) imageView.getDrawable());
 if (bitmapDrawable != null) {
 bitmapDrawable.getBitmap().recycle();
 }

But the above code always gives null in the value of bitmapDrawable. How can I fix this OutOfmemory exception?

P.S. The maximum size of the image drawables is 80kb

asked Oct 22, 2015 at 10:47
5
  • Answer from: stackoverflow.com/questions/27115944/… Maybe adding this line in Manifest on application tags will help you; android:largeHeap="true" Commented Oct 22, 2015 at 10:50
  • @Cüneyt Do I need to use android:largeHeap even for setting image on 80kb size? Commented Oct 22, 2015 at 10:52
  • 80 kb is not very big size. Actually I think you don't need android:largeHeap but I want to give a advice only. Commented Oct 22, 2015 at 10:58
  • first largeHeap is not a real solution, second, 80KB, no, in memory it takes more, see: Daniel Zolnai's answer Commented Oct 22, 2015 at 11:22
  • make a folder 'drawable-nodpi' and move these images to this folder. Hope it will help you Commented Oct 22, 2015 at 11:25

2 Answers 2

3

What are the pixel sizes of the images? As the images are stored in the java heap, they are not compressed. That means that each pixel of the bitmap can take up to 32 bits = 4 bytes in the heap. So with an image with the size of 1920 x 1080 (maybe you are also targeting large resolution tablets), that is:

1920 x 1080 x 4 bytes = 8294400 bytes, 8.29 megabytes.

Now that might be OK on a tablet, but on an old phone which might have a heap space of 64 Megabytes, you might easily run into OutOfMemoryExceptions.

So what can you do?

  1. If you are targeting phones only, you can resize the images to smaller sizes maybe? This is mainly based on trial and error, also depends on the usage of the image (blurred background image VS an image of a map with important details).

  2. Use a different bitmap config. The default is RGB_8888, which is 8 bits for each channel (ARGB) = 32 bits. If you don't need the alpha channel (transparency), and the image does not have to be super high quality, you should give RGB_565 a try. It has a very small quality decrease, but it's almost unnoticeable. In return it consumes halve the memory (5 + 6 + 5 = 16 bits per pixel).

  3. The most important fix: You can supply different images for different screen densities. So here's an example. Let's say we want to use the FullHD picture from the calculation. For smaller screens we scale it down, saving on memory. There are tools for scaling images down for the different densities, see this question. Following the density guidelines, you could put the following images with the sizes in the given directories:

    • drawable-xxhdpi: 1920x1080
    • drawable-xhdpi: 1280x720
    • drawable-hdpi: 960x540
    • drawable-mdpi: 640x360

    So while the image would take up 8.29 Mb heap space on a large tablet, it would only take up 921 Kb on an older phone, exactly what we wanted. It does come with the cost of increased APK size though, because now it contains 4 images instead of one.

answered Oct 22, 2015 at 11:16
Sign up to request clarification or add additional context in comments.

4 Comments

So it is not very likely that it was that image. One thing you should note that it is not necessarily that image which is taking up large memory space. It might be that another image of 30 Mb fitted in the memory, but the app just crashed when trying to add another smaller image, so it will point you to the smaller image, because that's when it crashed.
Is there a way I can recycle the old image before setting a new one?
If you use setImageResource(), then it is done automatically in the internals of BitmapDrawable (it makes sure that no pointer is kept on the bitmap, making it available for GC collecting).
What you should do is make a memory dump when the app is consuming a lot of memory (there is a chart for that in Android Studio), and take a memory dump. Then analyze it. Here's a really nice article about that: theshiftingbit.com/Fixing-Memory-Leaks-in-Android-Studio
0

I think your problem described well here

or you can change dimension of your image by photoshop to 50x50 etc.

answered Oct 22, 2015 at 11:07

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.