Android加载大图防止OOM
问题
在Android的开发过程中经常遇到多张大图片的加载,图片的类型是多种多样,不同大小。但是大多数的图片都是高分辨率,总体来说,远远大于我们要展示的容器ImageView。而加载过大图片就会导致OOM异常。下面就介绍解决该问题的途径
解决途径
Android图片Bitmap对象是用BitmapFactory工具类中多种解析方法创建的。创建的方式大概分为:、
1)SD卡文件中加载解析方式
public static Bitmap decodeFile(String pathName, Options opts) {}
2)资源中文件加载解析方式
public static Bitmap decodeResource(Resources res, int id, Options opts) {}
3)字节数组解析方式
public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {}
4)网络中加载流的解析方式
public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {}
这些方法会尝试为已经构建的bitmap分配内存,这时就会很容易导致OOM出现。为此每一种解析方法都提供了一个可选的BitmapFactory.Options参数,将这个参数的inJustDecodeBounds属性设置为true就可以让解析方法禁止为bitmap分配内存,返回值也不再是一个Bitmap对象,而是null。虽然Bitmap是null了,但是BitmapFactory.Options的outWidth、outHeight和outMimeType属性都会被赋值。这个技巧让我们可以在加载图片之前就获取到图片的长宽值和MIME类型,从而根据情况对图片进行压缩。
/** * 从SD卡中获取图片并且比例压缩 * @param path 路径 * @param mHeight 自定义高度 * @param mWidth 自定义宽度 * @return */ public static Bitmap getBitmapFromSDCard(String path, int mHeight, int mWidth) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); //计算比例值 options.inSampleSize = calculateInSampleSize(options,mHeight,mWidth); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(path, options); } /** * 计算压缩比例值inSampleSize * @param options 压缩的参数设置 * @param mHeight 想要的高度 * @param mWidth 想要的宽度 * @return */ public static int calculateInSampleSize(BitmapFactory.Options options, int mHeight, int mWidth) { //原尺寸大小 int yHeight = options.outHeight; int yWidth = options.outWidth; int inSampleSize = 1; //如果宽度大的话根据宽度固定大小缩放 if (yWidth > yHeight && yWidth > mWidth) { inSampleSize = (int) (yWidth / mWidth); } //如果高度高的话根据宽度固定大小缩放 else if (yWidth < yHeight && yHeight > mHeight) { inSampleSize = (int) (yHeight / mHeight); } if (inSampleSize <= 0) inSampleSize = 1; return inSampleSize; }
观察代码,可以看出,先后解析了两次图片,首先options.inJustDecodeBounds = true以后,BitmapFactory解析一次图片,将图片的得到的option传入到方法calculateInSampleSize方法中,在方法中可以根据ImageView控件的长宽对图片进行压缩,计算出合适的inSamplesize值,最后options.inJustDecodeBounds 设置 false以后,在对图片解析一次,这时的图片的比例值inSamplesize正是我们计算出来的值。
上面的这样做已经可以图片的比例压缩,至于有需要对图片质量压缩的可以参照一下代码。
/** * 图片质量压缩(质量参数) * @param image * @param quality 质量参数 百分之多少 例如:0.6 0.7 * @return */ public static Bitmap compressImage(Bitmap image, float quality) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, (int)quality*100, baos); ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中 return BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片 }
更多相关文章
- Android图片压缩浅谈
- android扫描sdcard中的音视频及图片等文件
- android的消息处理惩罚机制(图+源码解析)——Looper,Handler,Message
- Android(安卓)Activity全面解析
- Android单点触控技术,对图片进行平移,缩放,旋转操作
- (六)android recovery 升级UI显示之资源文件
- XML解析和生成之--pull(android内置)
- FontAwesome-用TextView显示图片
- .9图片的制作(draw9patch.bat工具的使用)