如何高效的加载一个Bitmap,这是一个很有意义的话题,因为在我们开发的过程中,经常会遇到这样错误”OutOfMemoryError”这样的错误,很多时候都是因为加载Bitmap出现的内存溢出.
如何加载一个Bitmap
Bitmap在andriod中指的是一张图片,那么如何加载一个图片?BitmapFactory类提供了四类方法:decodeFile,decodeResource,decodeStream和decodeByteFactroy,分别用于支持从文件系统,资源,输入流以及字节数组中加载一个对象,在四类方法最终在andriod的底层实现的,对应着BitmapFactory类的几个native方法.
如何高效的加载一个Bitmap?
其实核心思想很简单,就是使用BitmapFractory,Optins来加载所需尺寸的图片,通过二次采样的方法来缩小图片,从而也减少内存的消耗.
二次采样
1. 将BitmapFactory.Options的inJustDecodeBounds参数设为true
2. 从BitmapFactory.Options来缩放图片,其中它的inSampleSize参数即采样率,当inSampleSize=1的时候,采样率的大小和原图是相同的,当inSampleSize的大小大于1的时候(例如2),采样后的图片宽和高均为原本的1/2,而像素为原来的1/4.
3. 根据采样率的规则并结合目标的View的所需的大小计算出采样率inSampleSize.
4. 讲BitmapFactory.Optinons的inJustDecodeBounds参数设为false,然后重新加载图片
经过上面的几个步骤,加载的图片就是进行缩放后的图片,当然有时候并不需要缩放.在这里说明一下inJustDecodeBounds参数,当此参数设为true的时候,BitmapFactory只会解析图片原始宽/高的问题,而不会真正的去加载图片,因此这个操作是比较轻量级的.
public static Bitmap decodeSampleBitmapFromResource(Resource res,int resId,int reqWidth,int reqHeight){
final BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactroy.decodeResoure(res,resId,options);
options.inJustDecodeBounds=false;
return BitmapFactory.decodeResourse(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=width/2;
while((halfHeight/inSampleSize)>=reqHight &&(halfWidth/inSampleSize)>=reqWidth){
inSampleSize*=2;
}
}
return inSampleSize;
}
有了上面的两个方法,使用起来就简单多了,比如ImageView所期望的图片大小为100X100像素的时候,这个时候我们就可以通过如下的方式高效的加载并且显示图片:
mImageView.setImageBitmap(decodeSampledBitmapFromResourse(getResources(),R.id.myimage,100,100));