我是所有内存管理主题的新手,因此有很多我不理解的事情 我正在尝试在我的应用程序中缓存图像,但我的内存消耗有问题:
所有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用于什么?为什么会这样?
答案 0 :(得分:8)
图像也会根据密度进行缩放,因此可以使用大量内存。
例如,如果图像文件位于drawable
文件夹(密度为mdpi
)并且您在xhdpi
设备上运行,则宽度和高度都会加倍。也许this link可以帮助您,或this one。
因此,在您的示例中,图像文件将采用的字节为:
(1024 * 2)*(800 * 2)* 4 = 13,107,200字节。
如果你在xxhdpi
设备(如HTC one和Galaxy S4)上运行它会更糟。
你能做什么?将图像文件放在正确的密度文件夹(drawable-xhdpi
或drawable-xxhdpi
)中,或将其放入drawable-nodpi
(或在资源文件夹中),然后根据需要缩小图像。
顺便说一下,您不必设置options.inJustDecodeBounds = false
,因为它是默认行为。实际上,您可以为位图选项设置null。
关于向下缩放,您可以使用google's way或my way各有其优缺点。
关于缓存有很多方法可以做到。最常见的是LRU缓存。我最近创建了一个替代方案(链接here或here),它允许您缓存更多图像并避免使用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);