Android - 位图缓存占用大量内存

时间:2013-08-15 15:03:34

标签: java android caching bitmap

我是所有内存管理主题的新手,因此有很多我不理解的事情 我正在尝试在我的应用程序中缓存图像,但我的内存消耗有问题:

所有Bitmap Chaching代码都是从这里复制粘贴的:http://developer.android.com/training/displaying-bitmaps/index.html

我调试了代码并在eclipse的DDMS视图中检查了堆大小,在这些代码行之后大约有15mb的跳转:

        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);

在“decodeSampledBitmapFromResource”方法中。

图像为1024x800,75kb jpg文件。根据我在互联网上看到的情况,这个图像应该占用的内存大约是1024 * 800 * 4(每像素字节数)= 3.125mb

关于这个主题的所有主题都没有说明为什么它会占用更多的内存。有没有办法用合理数量的内存缓存一个图像?

修改

我尝试使用@ ArshadParwez下面的答案中建议的decodeFile方法。使用此方法,在BitmapFactory.decodeStream方法之后,内存仅增加了3.5mb - 问题解决了,但是我希望直接从资源缓存位图。

我注意到在decodeResource方法中有2个内存“跳跃” - 一个大约3.5mb - 这是合理的,另一个奇怪的是14mb。那些14mb用于什么?为什么会这样?

3 个答案:

答案 0 :(得分:8)

图像也会根据密度进行缩放,因此可以使用大量内存。

例如,如果图像文件位于drawable文件夹(密度为mdpi)并且您在xhdpi设备上运行,则宽度和高度都会加倍。也许this link可以帮助您,或this one

因此,在您的示例中,图像文件将采用的字节为:

  

(1024 * 2)*(800 * 2)* 4 = 13,107,200字节。

如果你在xxhdpi设备(如HTC one和Galaxy S4)上运行它会更糟。

你能做什么?将图像文件放在正确的密度文件夹(drawable-xhdpidrawable-xxhdpi)中,或将其放入drawable-nodpi(或在资源文件夹中),然后根据需要缩小图像。

顺便说一下,您不必设置options.inJustDecodeBounds = false,因为它是默认行为。实际上,您可以为位图选项设置null。

关于向下缩放,您可以使用google's waymy way各有其优缺点。

关于缓存有很多方法可以做到。最常见的是LRU缓存。我最近创建了一个替代方案(链接herehere),它允许您缓存更多图像并避免使用OOM,但它会给您带来很多责任。

答案 1 :(得分:7)

您可以使用此方法传递图像并从中获取位图:

public Bitmap decodeFile(File f) {
    Bitmap b = null;
    try {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;

        FileInputStream fis = new FileInputStream(f);
        BitmapFactory.decodeStream(fis, null, o);
        fis.close();
        int IMAGE_MAX_SIZE = 1000;
        int scale = 1;
        if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
            scale = (int) Math.pow(
                    2,
                    (int) Math.round(Math.log(IMAGE_MAX_SIZE
                            / (double) Math.max(o.outHeight, o.outWidth))
                            / Math.log(0.5)));
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        fis = new FileInputStream(f);
        b = BitmapFactory.decodeStream(fis, null, o2);
        fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return b;
}

答案 2 :(得分:1)

@Ori Wasserman:根据您的要求,我使用了一种方法从资源文件夹中获取图像,我也使用了7 MB图像。我将7 MB图像放在“res-> drawable”文件夹中,并使用以下代码,它没有崩溃,图像显示在imageview中:

 Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.image_7mb);
 loBitmap = Bitmap.createScaledBitmap(image, width_of_screen , height_of_screen, true);
 imageview.setImageBitmap(loBitmap);