尊重原创,转发请注明出处。
图片是安卓开发里绕不过的一个问题,涉及到图片,特别是大图片的加载,很经常会报OOM内存泄露的问题,所以如何解决图片占用过大内存的问题也是我们在开发过程中经常会碰到的,下面就讲一个解决图片过大造成内存泄露很经常也很实用的办法。
其实在日常开发中,图片很大,但是很多情况我们可能只是希望加载一个缩略图回来,比如头像等等,这个时候如果我们不做任何处理,就硬生生把原图加载进来,那一张好几兆的图片显然不是我们内存可以承受的,我们也实在没必要去加载原图,所以我们在把图片加载回来之前如果能根据具体情况来决定要加载多大的图片回来,这样显然是更好的方法 ,也显得更加优雅,而不是那么暴力,所以接下来就介绍这种方法的实现。
这里主要是用到BitmapFactory.Options来实现控制加载回来图片的像素的大小,他的实现原理是:
第一步:“假加载”,去获取目标图片的手机大小。设置options.inJustDecodeBounds = true;再去 BitmapFactory.decodeFileDescriptor(fd, null, options);加载目标图片,因为设置了 options.inJustDecodeBounds = true;所以他实际上并不会真的去加载目标图片,而是只返回目标图片的 大小。
第二步:根据返回的目标图片的实际大小,以及你希望加载回来图片的大小,来计算出需要缩略的倍数。下面是一个实现计算缩 略倍数的函数。
//对图片进行合适的缩放,即返回一个缩放多少倍(即你给他传一个option,它从里面提取出图片的真实宽度高度,然后你把你想要的目标大小传给它,计算出应该缩小多少倍了)
public static int computeSampleSize(Options options, int target) {
int w = options.outWidth;
int h = options.outHeight;
int candidateW = w / target;
int candidateH = h / target;
int candidate = Math.max(candidateW, candidateH);
if(candidate == 0) {
return 1;
}
if(candidate > 1) {
if((w > target) && (w / candidate) < target) {
candidate -= 1;
}
}
if(candidate > 1) {
if((h > target) && (h / candidate) < target) {
candidate -= 1;
}
}
return candidate;
}
第三步:上面两部实现了计算出应该缩略的倍数,所以最后就可以利用BitmapFactory.Options去真正加载图片的缩略图 回来了,具体做法:
options.inJustDecodeBounds = false; (说明是真的去加载图片了)
options.inSampleSize =8(即缩放8倍)。
Bitemap b=BitmapFactory.decodeStream(in, null, options);//加载返回像素缩小8倍的那张图片(这里in 是流,通过流的方式加载)
为了节约内存,我们还可以给option设置以下几条:
options.inDither=false; /*不进行图片抖动处理*/
options.inPreferredConfig=null; /*设置让解码器以最佳方式解码*/
/* 下面两个字段需要组合使用 */
options.inPurgeable = true;
options.inInputShareable = true;
通过以上这种做法就能加载回来自己想要的像素的缩略图,可以大大的减少内存空间的同时也更加符合我们的实际需要,也避免了程序要是因为大图片的原因而产生OOM的错误,大大提高了app的用户体验。
关于bitmap加载目标图片缩略图来解决内存泄露的问题就暂时说到这里。