Android BitmapFactory的OutOfMemoryError解决方案

无简介

情景再现

今天写了两个东西,一个是通过照相机拍摄照片,然后获得照片之后将它设置到ImageView上面,另一个是通过相册,或者文件获得照片,放到ImageView上面。 一开始,一切正常 然后我做了下面的操作: 点击拍照,将拍到的照片放到了ImageView上面,然后我又点击拍照,在放到ImageView上面的时候崩溃了。OutOfMemory

我的代码是这样写的:

  • 点击按钮的操作

Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.setType(“image/*”);
startActivityForResult(i, 1);

  • onActivityResult里面

Uri uri = data.getData();
mBitmap = getBitmapFromUri(uri);
iv.setImageBitmap(mBitmap);//iv是ImageView的

  • getBitmapFromUri中的代码:

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
return bitmap;

程序崩溃在了getBitmap(this.getContentResolver(), uri)。 然后我打开了getBitmap方法,里面的代码是这样的:

public static final Bitmap getBitmap(ContentResolver cr, Uri url) throws FileNotFoundException, IOException {
InputStream input = cr.openInputStream(url);
Bitmap bitmap = BitmapFactory.decodeStream(input);
input.close();
return bitmap;
}

它直接调用了decodeStream(input)。

经过总结发现,估计是因为G3手机拍摄相片分辨率过高,使图片过大,造成过程中内存溢出,通过网上搜索若干解决加载大图片时内存溢出的问题: 尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。

详情请点击查看

解决办法

只修改了一个地方,就是getBitmap中的decodeStream的调用。 下面是修改后的getBitmapFromUri方法:

private Bitmap getBitmapFromUri(Uri uri) {
try {
// 读取uri所在的图片
//Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
InputStream input = this.getContentResolver().openInputStream(uri);
BitmapFactory.Options opts=new BitmapFactory.Options();
opts.inTempStorage = new byte[100 * 1024];
//3.设置位图颜色显示优化方式
//ALPHA_8:每个像素占用1byte内存(8位)
//ARGB_4444:每个像素占用2byte内存(16位)
//ARGB_8888:每个像素占用4byte内存(32位)
//RGB_565:每个像素占用2byte内存(16位)
//Android默认的颜色模式为ARGB_8888,这个颜色模式色彩最细腻,显示质量最高。但同样的,占用的内存//也最大。也就意味着一个像素点占用4个字节的内存。我们来做一个简单的计算题:3200*2400*4 bytes //=30M。如此惊人的数字!哪怕生命周期超不过10s,Android也不会答应的。
opts.inPreferredConfig = Bitmap.Config.RGB_565;
//4.设置图片可以被回收,创建Bitmap用于存储Pixel的内存空间在系统内存不足时可以被回收
opts.inPurgeable = true;
//5.设置位图缩放比例
//width,hight设为原来的四分一(该参数请使用2的整数倍),这也减小了位图占用的内存大小;例如,一张//分辨率为2048*1536px的图像使用inSampleSize值为4的设置来解码,产生的Bitmap大小约为//512*384px。相较于完整图片占用12M的内存,这种方式只需0.75M内存(假设Bitmap配置为//ARGB_8888)。
opts.inSampleSize = 4;
//6.设置解码位图的尺寸信息
opts.inInputShareable = true;
Bitmap bitmap = BitmapFactory.decodeStream(input,null,opts);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

以上方法通过使用BitmapFactory.Options以牺牲图片质量为代价,减少了内存的消耗。 [dl href=‘http://pan.baidu.com/s/1c02PZQK’]测试代码下载(选择图库图片并设置到ImageView上)[/dl]

-------------本文结束  感谢您的阅读-------------
下次一定