OutOfMemory while setting image in ImageView

2019-02-25 14:38发布

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

2条回答
\"骚年 ilove
2楼-- · 2019-02-25 14:46

I think your problem described well here

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

查看更多
\"骚年 ilove
3楼-- · 2019-02-25 15:00

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.

查看更多
登录 后发表回答