Android BitmapFactory 的 OutOfMemoryError 解决方案 – 热爱改变生活
我的GitHub GitHub |     登录
  • If you can't fly, then run; if you can't run, then walk; if you can't walk, then crawl
  • but whatever you do, you have to keep moving forward。
  • “你骗得了我有什么用,这是你自己的人生”
  • 曾有伤心之地,入梦如听 此歌

Android BitmapFactory 的 OutOfMemoryError 解决方案

Android其他 sinvader 3474℃ 0评论

情景再现

今天写了两个东西,一个是通过照相机拍摄照片,然后获得照片之后将它设置到 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 以牺牲图片质量为代价,减少了内存的消耗。

测试代码下载(选择图库图片并设置到 ImageView 上)
¥ 有帮助么?打赏一下~

转载请注明:热爱改变生活.cn » Android BitmapFactory 的 OutOfMemoryError 解决方案


本博客只要没有注明“转”,那么均为原创。 转载请注明链接:sumile.cn » Android BitmapFactory 的 OutOfMemoryError 解决方案

喜欢 (0)
发表我的评论
取消评论
表情

如需邮件形式接收回复,请注册登录

Hi,你需要填写昵称和邮箱~

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址