Android 加载图片过程导致内存溢出(Out Of Memory)

释放双眼,带上耳机,听听看~!

 

加载图片的时候,啪啪啪就OOM了。

解决图片OOM之前,先来了解一下一张图片内存占用的相关因素——图片质量,图片尺寸,填充区域

图片质量

质量就是图片大小(多少MB,多少KB)。相对情况下图片越大,占用内存越大

图片尺寸

图片尺寸=图片的宽高,相对情况下宽高越大,占用内存越大

填充区域

填充区域就是图片显示在屏幕上的大小,可以理解为ImageView的大小。相对情况下宽高越大,占用内存越小。 (有些人一直错误理解为imageView越小,占内存越小。举个例子,一张10MB原本放在一个10000*10000的容器里,他没什么压力。把它扔进一个10*10的容器里,能不出事吗?一吨水在一个大缸子里好好的,你换一个矿泉水瓶去装一吨水,能不溢出?)
PS:因为项目里,imageView的大小基本是固定的,所以不从这个方向去考虑减少内存。这里提到填充区域,因为有不少人是头像设置的时候引发OOM,列表的头像一般都是30*30到60*60,区域很小,有些人上传了原始尺寸图片,来源各种各种,有些设置几千x几千,然后就OOM了。

了解了内存占用相关要素以后,解决方案就很直接了,就是去改变这些相关要素。

1 图片质量压缩

    private Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中  
int options = 100;
while ( baos.toByteArray().length / 1024>100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩         
baos.reset();//重置baos即清空baos  
image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中  
options -= 10;//每次都减少10  
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中  
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片  
return bitmap;
}

图片压缩的方法网上很多,我也是网上copy的,一般项目里就直接使用Glide压缩了

2 重新设置图片大小

    public Bitmap zoomImg(Bitmap bm, int newWidth ,int newHeight){
// 获得图片的宽高   
int width = bm.getWidth();
int height = bm.getHeight();
// 计算缩放比例   
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 取得想要缩放的matrix参数   
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 得到新的图片
Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
return newbm;
}

建议使用三方库,比如glide里就有个.override(width,height)的方法,在算出bitmap等比例缩小到imageView上显示的宽高,然后调用重新设置宽高的方法。

3 图片内存回收

上面说的两种方法是在图片显示的时候减少内存。而图片使用过后呢,关闭Activity之后,图片有一段时间是不会马上回收的,可以调用一下recycle()方法。又或者你是列表分页场景,可以在上分页后,清除掉上分页中
imgURl的缓存。具体参照业务需求,有些需求本身就是要求各种缓存来节省流量的。

图片压缩和图片重设宽高建议直接用三方库啊,Glide,Picasso都比较常见了。

人已赞赏
Android文章

Android 共同处理touch事件

2020-4-13 23:32:12

Android文章

Animation用法_animation动画效果

2020-4-14 0:46:48

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索