我的应用程序将有超过350张图像,这些图像将从数据库中解码。我根据图像数据创建位图,并根据设备屏幕分辨率进行缩放。当我试图将所有这些位图保存到内存中时,我面临outOfMemory异常。然后在各个地方推荐使用BitmapFactory.Options.inPurgeable作为避免OutOfMemoryExceptions的方法。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
options.inInputShareable = true;
Bitmap bitmap = BitmapFactory.decodeByteArray(imagaeData, 0, size, options);
...
..
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, true);
我将这个缩放的位图缓存到HashMap并将其用于图像视图。在将位图加载到内存时,我再次遇到OutOfMemory异常。我不知道inPurgeable是否适用于我的情况。我想知道缩放的位图是否会引用字节数组。当我使用缩放位图时,它是否具有decodeByteArray中使用的inPurgeable选项的效果。我无法弄清楚如何处理这个位图内存问题。感谢您的帮助。
答案 0 :(得分:0)
另外:当你创建一个缩放的位图时,你将它们存储在内存中两次 - >内存中的700个图像太过分了。您应该检查是否最好在选项上使用inScale
再次将其减少到350并减少内存占用量。
我仍然认为,即使在优化的方式中,350张图片太多了。您应该考虑延迟加载解决方案。
答案 1 :(得分:0)
您可以尝试使用BitmapFactory.Options.inScaled& BitmapFactory.Options。 inScreenDensity获取缩放的位图。
您需要一种更好的方法来缓存内存中的位图。你最好在HashMap中为位图保存Bitmap的WeakReference,你可以切换到LinkedHashMap来实现简单的LRU缓存。
你真的不需要缓存所有图像,因为它们永远不会有机会在一个屏幕上显示。
答案 2 :(得分:0)
你真的应该考虑使用类似Square's Picasso lib的东西来处理图像加载和缩放。 Picasso处理“ImageView回收并在适配器中下载取消”,“自动内存和磁盘缓存”以及“最小化内存使用的复杂图像转换”。
答案 3 :(得分:0)
使用此方法首先缩小图像尺寸(文件指向SD卡上的照片)
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1=new FileInputStream(f);
BitmapFactory.decodeStream(stream1,null,o);
stream1.close();
//Find the correct scale value. It should be the power of 2.
// maximum size is 50
final int REQUIRED_SIZE=40;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<=REQUIRED_SIZE || height_tmp/2<=REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
FileInputStream stream2=new FileInputStream(f);
Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
//以下是调用上述方法的方法
String path = "/mnt/sdcard/DCIM/camera/IMG_2001.jpg";
Drawable background = hash_map.get(path);
if (background == null) {
try {
Bitmap bitmap = decodeFile(new File(path));
background = new BitmapDrawable(bitmap);
if (hash_map.size() > 600) {
// to prevent HashMap from growing too large.
hash_map.clear();
}
hash_map.put(path, background);
} catch (Throwable e) {
// in case there is an exception, like running out of memory.
if (e instanceof OutOfMemoryError) {
hash_map.clear();
}
}
}