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

Java Android-位图缓存占用大量内存,java,android,caching,bitmap,Java,Android,Caching,Bitmap,我对所有的内存管理科目都是新手,所以有很多事情我不懂。 我正在尝试在我的应用程序中缓存图像,但其内存消耗有问题: 所有位图更改代码几乎都是从这里复制粘贴的: 我调试了代码并在eclipse的DDMS视图中检查了堆大小,在这些代码行之后大约有15mb的跳转: options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); 在“decodeSa

我对所有的内存管理科目都是新手,所以有很多事情我不懂。
我正在尝试在我的应用程序中缓存图像,但其内存消耗有问题:

所有位图更改代码几乎都是从这里复制粘贴的:

我调试了代码并在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方法中有两个内存“跳跃”-一个大约3.5mb-这是合理的,另一个奇怪的14mb。这些14mb用于什么?为什么会发生这种情况?

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

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;
}

@Ori Wasserman:根据您的要求,我使用了一种方法从资源文件夹中获取图像,而且我也使用了7MB的图像。我将7MB的图像放在“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);

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

例如,如果图像文件位于
drawable
文件夹(即
mdpi
density)中,并且您在
xhdpi
设备上运行它,则宽度和高度都将加倍。也许可以帮你,或者

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

(1024*2)*(800*2)*4=13107200字节

如果在
xxhdpi
设备上运行(如HTC one和Galaxy S4),情况会更糟

你能做什么?将图像文件放入正确的密度文件夹(
drawable xhdi
drawable xxhdpi
)或将其放入
drawable nodpi
(或资产文件夹)并根据需要缩小图像的比例

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

关于向下扩展,您可以使用其中一种方法,或者每种方法都有自己的优缺点


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

将其缓存到文件系统而不是活动内存如何?@PaulNikonowicz,即使它解决了问题,辅助内存可能是闪存或类似类型,频繁写入会缩短其使用寿命,而主内存则不是。4字节用于ARGB4444。你确定它不是argb888吗?@diegocnascemento secondary memory并不一定意味着带有Android设备的闪存卡。即使它是8字节,也应该是6.25mb。我不想避免缓存,这不是一个解决方案。必须有一个正确的方法。我在处理图像时也遇到了很多崩溃,比如OutOfMemoryError。然后我用一些数学方法做了这个方法,之后我甚至可以使用5mb大小的图像而不会崩溃。在我尝试之前,我想了解原因-你是说BitmapFactory.decodeStream比BitmapFactory.decodeStream解码更好?不是这样的,我之所以使用decodeStream,是因为我使用了一个图像文件作为输入,它使用的是一个FileInputStream,如果它是一个资源文件,那么我会使用DecodeSourceResource,那么这比decodeSampledBitmapFromResource更好,如所示?该链接中的方法和我使用的方法不同,因为我正在将图像的最大大小固定为是1000像素,而且如果你使用我的代码,你不会看到输出图像有太多的退化,而该链接的代码会大大降低输出图像的质量。实际上,它将使用比你所说的更多的RAM,只是在很短的时间内。原因是您创建了原始位图和一个小位图。您不会注意到它,因为大图像将在下一次GC中处理。最关键的一点是,你要创建两个位图来实现一个单一的目标,这对内存来说是非常令人沮丧的。尝试使用此问题中的BitmapFactory.Option.ok。我忘记了关于位图的另一个技巧:您可以设置它们的格式,因此如果您不需要透明度,而且质量也不太重要,您可以使用RGB_565(每像素使用2个字节),而不是默认的ARGB_8888(每像素使用4个字节)。此处链接:。甚至在谷歌IO网站上,也有一些关于内存和位图的视频。我建议观察他们,即使他们没有谈论你的问题。