Bitmap的加载

先看看这个异常:
java.lang.OutofMemoryErroe:bitmap size exceeds VM budget
在开发时常遇到,android对单个应用的内存限制在16MB,但是现在手机种类繁多,各个厂商不同的手机版本和型号有所不同分配的内存也不同。在加载Bitmap的时候很容易造成内存溢出。因此高效地加载Bitmap是一个很重要也很容易被我们忽视的问题。


在Android中Bitmap指的是一张图片,可以是png、jpg格式等常见的图片格式,如何加载一个Bitmap呢?
BitmapFactory类提供了四类方法:decodeFile、decodeStream、decodeResource、decodeByteArray,分别从文件系统,输入流,资源,字节数组中加载一个Bitmap对象,其中decodeFile和decodeResource又间接调用了decodeStream方法,这四类方法最终在android底层实现的。对应着BitmapFactory类的几个native方法。


高效的加载一个Bitmap需要采用BitmapFactory.options来加载所需尺寸的图片,开发中我们使用的控件往往没有(例如:ImageView)图片的原始尺寸那么大,这时把这个图片加载进来在设置给控件显然没必要,因为控件并没有办法显示原始图片。通过BitmapFactory.options就可以按一定的采样率加载缩小图片,将缩小后的图片在控件上显示,这样会降低内存占用在一定程度上避免OOM.


通过BitmapFactory.options来缩放图片,主要是用到它的inSampleSize参数,即采样率。inSampleSize的取值应该总是2的指数,例如 1、2、4、6、8、16、32……等。比如为2时,采样后的图片大小为原图大小1/2,而像素为原图的1/4,占有内存大小也为原图的1/4.拿一张1024*1024像素的图片来说,假定采用ARGB8888格式存储,那么它占用内存为1024*1024*4,即 4 MB,如果inSampleSize为2,那么采样后的图片内存占用只有512*512*4,即 1 MB,如果外界传递给系统的inSampleSize不为 2 的指数,那么系统会向下取整应选择一个最接近的 2 的指数代替,比如3,系统会选择2 来代替。但是这个结论并非在所有的android版本上都成立。因此只是一个开发建议。


通过采样率即可有效地加载图片,开发中我们如何获取采样率呢?
主要分四步:
1.将BitmapFactory.options的inJustDecodeBounds参数设为true,并加载图片。
2.从BitmapFactory.options中取出图片的原始宽高信息,这个操作是轻量级的,并不会真正去加载图片。它们对应于outWidth 和 outHeight参数。
3.根据采样率的规则并结合目标View的所需大小计算inSampleSize.
4.将BitmapFactory.options 的inJustDecodeBounds参数设为false,重新加载图片。
将上面的4个流程用程序实现,代码:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth ,int reqHeight){
     final BitmapFactory.Options  options = new BitmapFactory.Options();
     options.inJustDecodeBounds = true;
     BitmapFactory.decodeResource(res,resId, options);
     //Calculate inSampleSize
     options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);
     options.inJustDecodeBounds = false;
     return BitmapFactory.decodeResource(res, resId,options);
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight){
     final int height = options.outHeigth;
     final int width  = optiosn.outWidth;
     int inSampleSize = 1;
     if (height > reqHeight || width > reqWidth ){
         final int halfHeight  = height / 2;
         final int halfWidth   = width / 2;
         while((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >=reqWidth.){
             inSampleSize *=2;
         }
    }
    return inSampleSize;
}
我们在实际使用时就更简单了,比附ImageView所期望的图片大小为100*100像素,这个时候就可以通过如下方式高效加载并显示图片:
mImageView.stImageBitmap(decodeSampleBitmapFromResource(getResource(), R.id.icon,100,100));
BitmapFactory的四个方法都支持采样加载,并且处理方式类似。但是decodeStream方法稍微特殊。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值