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 5667℃ 0评论

情景再现

今天写了两个东西,一个是通过照相机拍摄照片,然后获得照片之后将它设置到 ImageView 上面,另一个是通过相册,或者文件获得照片,放到 ImageView 上面。

一开始,一切正常

然后我做了下面的操作:

点击拍照,将拍到的照片放到了 ImageView 上面,然后我又点击拍照,在放到 ImageView 上面的时候崩溃了。OutOfMemory

我的代码是这样写的:

  • 点击按钮的操作
  1. Intent i = new Intent(Intent.ACTION_GET_CONTENT);
  2. i.setType("image/*");
  3. startActivityForResult(i, 1);
  • onActivityResult 里面
  1. Uri uri = data.getData();
  2. mBitmap = getBitmapFromUri(uri);
  3. iv.setImageBitmap(mBitmap);//iv 是 ImageView 的
  • getBitmapFromUri 中的代码:
  1. Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
  2. return bitmap;

程序崩溃在了 getBitmap(this.getContentResolver(), uri)。

然后我打开了 getBitmap 方法,里面的代码是这样的:

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

它直接调用了 decodeStream(input)。

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

详情请点击查看

解决办法

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

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

以上方法通过使用 BitmapFactory.Options 以牺牲图片质量为代价,减少了内存的消耗。

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

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


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

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

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

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

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