情景再现
今天写了两个东西,一个是通过照相机拍摄照片,然后获得照片之后将它设置到 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 解决方案