由于 Bitmap 的特殊性和 Android 对于每一个应用所施加的内存限制,就会导致加载图片可能会出现 OOM 内存溢出,所有要如何高效加载一个图片是很重要的。
那么在 Android 如何加载一个图片呢?BitmapFactory 类提供了四种方法:decodeFile、decodeResource、decodeStream、decodeByteArray。从它们名字我们就可以看出,它们分别支持从文件系统、资源、输入流和字节数组中加载 Bitmap 对象,其中 decodeFile 和 decodeResource 又间接调用了 decodeStream。
那么如何高效加载图片呢?核心思想就是使用 BitmapFactory.Options 来加载所需尺寸的图片。例如当使用 ImageView 加载图片,当图片原始尺寸比 ImageView 大时,就需要使用 BitmapFactory.Options 将图片以一种比例缩小。这样加载缩小的图片展现到 ImageView 上,就可以降低内存在一定程度上避免 OOM。
通过 BitmapFactory.Options 来缩放图片,主要是利用了它的 inSampleSize 参数,即采样率。当 inSampleSize 为1时,图片为原图大小,当 inSampleSize = n(n>1) 时,图片高宽均为原来的 1/n,像素为原来的 1/(n*n),内存也为原来的 1/(n*n)。
如果,ImageView 和 Bitmap 高宽是相同的比率,那么直接缩放基本上没有问题,但是如果比率不同,图片缩放得稍小就会被拉伸导致模糊。
- 如何获取采样率
- 将 BitmapFactory.Options 的 inJustDecodeBounds(此参数为 true 时,BitmapFactory 只会解析图片的原始高宽,而不会加载,所以是一个轻量级操作)参数设为 true,并加载图片。
- 从 BitmapFactory.Options 中取出的原始高宽对应为 outWidth、outHeight。
- 利用采样率规则和 VIew 的所需大小计算采样率 inSampleSize 。
- 将 BitmapFactory.Options 的 inJustDecodeBounds 设为 false,重新加载图片。
public static Bitmap decodeSampleBitmapFromResources(Resources res,int resId
,int reqWidth,int reqHeight){
final BitmapFactory.Options options = new BitmapFactory.Options();
//设置 inJustDecodeBounds 参数为true,解析原图
options.inJustDecodeBounds = true;
//加载原图
BitmapFactory.decodeResource(res,resId,options);
//获取采样率
options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);
//设置 inJustDecodeBounds 参数为false,不解析原图
options.inJustDecodeBounds = false;
//返回压缩后的图片
return BitmapFactory.decodeResource(res,resId,options);
}
public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
//获取图片原始的宽高
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
//先判断图片是否需要压缩
if (height > reqHeight || width > reqWidth){
final int halfHeight = height/2;
final int halfWidth = height/2;
//直到压缩到比需要大小小
while ((halfHeight / inSampleSize)>= reqHeight
&& (halfWidth / inSampleSize)>= reqWidth){
inSampleSize*=2;
}
}
return inSampleSize;
}
当我们需要高效加载图片时,可以就直接调用 decodeSampleBitmapFromResources()方法。而BitmapFactory的其它三个方法也是试用的。
大家如果感兴趣可以看我下一篇 Android 缓存策略。
学习自《Android 开发艺术探索》
本文介绍在Android中如何高效地加载图片以避免内存溢出。主要通过BitmapFactory.Options配置项中的inSampleSize参数来按比例缩小图片,从而减少内存消耗。
410

被折叠的 条评论
为什么被折叠?



