- 当CPU要读取数据时,先访问缓存区如果没有才会进入内存中查找,缓存策略用于很多场合,在实际开发过程中图片经常需要用到Bitmap做缓存,目前比较常用的缓存策略有LruCache 和 DiskLruCache
LruCache:当缓存快满的时候,会淘汰近期最少使用的缓存目标,可以在内存中缓存数据
DiskLruCache:与LruCache是一样的思路,不过操作的是本地磁盘中的文件实体,操做比较复杂,不是Android 内置的库,需要存储权限
1.采样率的获取(高效加载图片)
高效的加载Bitmap就需要采用BitmapFectory.Options来加载所需尺寸的图片,通过BitmapFectory.Options来缩放图片,主要是用到了它的inSimpleSize(采样率)参数
inSimpleSize <= 1 :图片保持原有的大小
inSimpleSize > 1 :图片根据1/(inSimpleSize 的平方)进行缩小,一般inSimpleSize取值为2的倍数,甚至有的版本如果不是2的倍数,会向下取整并选择一个最接近2的倍数的数来代替
- 【注意事项】从实际情况出发,采样率尽量应与ImageView的大小缩放到相同的相同的程度,当不能做到大小相同的程度,尽量选择比ImageView 略大,如果选择较小的就会使图片被拉伸,图片变得模糊
- 如何获得采样率:
- (1)将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片
- (2)从BitmapFactory.Options中取出图片的原始信息,他们对应参数outWidth和outHeight参数
- (3)计算采样率
- (4)将BitmapFactory.Options的inJustDecodeBounds参数设为false,然后重新加载图片
public static Bitmap decode(Resources res,int resId,int reqwidth,int reqhight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res,resId,options);
options.inSampleSize = calculateInSampleSize(options,reqwidth,reqhight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res,resId,options);
}
public static int calculateInSampleSize(BitmapFactory.Options options,int w,int h) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSamplesize = 1;
if (height > h || width > w) {
final int hh = height / 2;
final int hw = width / 2;
while ((hh / inSamplesize) > h && (hw / inSamplesize) >= w) {
inSamplesize *= 2;
}
}
return inSamplesize;
}
2.缓存策略
用于Android设备上的程序,多数使用流量,而当我们需要网络上的图片时,不能让用户每次使用都需要消耗流量去加载,这时我们就需要使用-----缓存
当程序第一次从网上加载图片后,就缓存到存储设备上,下次使用就不再从网络上获取
- 读取顺序
【内存】—>【储存设备】----->【网络下载】
而缓存区的大小也是有限的,这就需要我们在适当的时候使用缓存算法更新缓存区, - LRU算法的基本思想:当缓存区满时,就将最后修改时间较早的缓存移除,主要分为LruCache 和 DiskLruCache
(1)LruCache
LruCache是一个泛型类,内部采用LinkedHashMap以强引用的方式存储到外界的缓存对象。 - 强引用:直接的对象调用
- 软引用:当一个对象只有软引用存在时,内存不足时,此对象会被gc 回收
- 弱引用:当一个对象只有弱引用存在时,此对象随时会被gc回收
【创建】
int max = (int)(Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = max / 8;
LruCache<String,Bitmap> stringBitmapLruCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
//计算缓存对象大小
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
};
【缓存的获取】
stringBitmapLruCache.get(key);
【缓存的添加】
stringBitmapLruCache.put(key,value);
【缓存的删除】
stringBitmapLruCache.remove(key);