- 有效的处理较大的位图
图像有各种不同的形状和大小。许多情况下,他们往往比一个典型应用程序的用户界面(UI)所需要的资源更大。
读取一个位图的尺寸和类型:
为了从多种资源来创建一个位图,BitmapFactory类提供了几个解码的方法(decodeByteArray(),decodeFile(),decodeResource(),等等)。根据你的图像数据资源选择最合适的解码方法。这些方法试图请求分配内存来构造位图,因此很容易导致OutOfMemory异常。每种类型的解码方法都有额外的特征可以让你通过BitMapFactory.Options类指定解码选项。当解码时避免内存分配可以设置inJustDecodeBounds属性为true,位图对象返回null但是设置了outWidth,outHeight和outMimeType。这种技术允许你在创建位图之前去读取图像的尺寸和类型。
加载一个缩小版本到内存中:
现在的图像尺寸都是已知的,他们可以被用来决定是否应该加载完整的图片到内存或者是否用一个缩小的版本去代替加载。一下是值得考虑的因素:
*估计加载完整图像所需要的内存;
*你承诺加载这个图片所需空间带给你的程序的其他内存需求;
准备加载图像的目标ImageView或UI组件尺寸;
当前设备的屏幕尺寸和密度;
例如,如果1024768像素的图像最终被缩略地显示在一个12896像素的ImageView中,就不值得加载到内存中去。
例子
位图重新采样
public Bitmap decodeSampledBitmapBitmapFromResource(Resources res,int resid,int reqWidth,int reqHeight){
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactory.decodeResource(res,resid,options);
options.inSampleSize=calculateInSampleSize(options,reqWidth,reqHeight);
options.inJustDecodeBounds=false;
return BitmapFactory.decodeResource(res,resid,options);
}
计算位图的采样比例
public int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
//获取位图的原宽高
int w=options.outWidth;
int h=options.outHeight;
int inSampleSize=1;
if (w>reqWidth||h>reqHeight){
if (w>h){
inSampleSize=Math.round((float) h/(float) reqHeight);
}else {
inSampleSize=Math.round((float) w/(float) reqWidth);
}
}
return inSampleSize;
}
按钮事件
public void showClick(View v){
Bitmap bitmap= decodeSampledBitmapBitmapFromResource(getResources(),R.mipmap.b,100,100);
imageView.setImageBitmap(bitmap);
}
效果图
- 缓存位图
(1)内存缓存:
内存缓冲提供了可以快速访问位图LruCache类用于缓存位图的任务,最近被引用的对象保存在一个强引用LinkedHashMap中,以及在缓存超过了其指定的大小之前释放最近很少使用的对象的内存。
注:LRU是Least Recently Used 近期最少使用算法
(2)磁盘缓存:
使用磁盘缓存来持续处理位图,并且有助于在图片内存缓存中不再可用时缩短加载时间,当然,从磁盘获取图片比从内存加载更慢并且应当在后台线程中处理,因为磁盘读取的时间是不可预知的,注意:如果它们被更频繁地访问,那么一个ContentProvider可能是一个更合适的地方来存储缓存中的图像。
第三方DisLruCache解决方案