1.Bitmap的高效加载
核心思想:按一定的采样率将图片缩小后在加载进来
BitmapFactory.Options的参数
a.inSampleSize参数:即采样率,同时作用于宽/高
取值规定:
应为2的指数,如1,2,4,8.. 否则系统会向下取整并选择一个最接近2的指数来替代,如3被2替代。
变换规则:
当inSmapleSize=1,采样后大小不变
当inSampleSize=K>1 采样后图片会缩小。具体规则:宽高变为原图的1/K,像素变为原图的1/k^2,占用内存
大小变为原图的1/k^2.
注意:根据图片宽高的实际大小和需要的大小 从而计算出缩放比尽可能取最少,避免由于缩小的过多,导致在控件中不能铺满而被拉伸至模糊。
//计算采样率大小
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
//采样率
int inSampleSize = 1;
//判断图片的宽高之一是否大于所需宽高
if (height > reqHeight || width > reqWidth) {
//图片宽高之一大于所需宽高,那么宽高都除以2
final int halfHeight = height / 2;
final int halfWidth = width / 2;
//循环宽高除以采样率的值,如果大于所需宽高,采样率inSampleSize翻倍
//PS:采样率每变大2倍,图片大小缩小至原来大小的1/4
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
//下面逻辑是为了处理一些不规则图片,如一张图片的height特别大,远大于width,此时图片的大小很大,
//此时加到内存中去依然不合适,算出总此时图片总像素大小totalPixels
long totalPixels = width * height / inSampleSize;
//如果图片总像素大于所需总像素的2倍,继续扩大采样率
final long totalReqPixelsCap = reqHeight * reqWidth * 2;
while (totalPixels > totalReqPixelsCap) {
inSampleSize *= 2;
totalPixels /= 2;
}
}
//返回最终的采样率inSampleSize
return inSampleSize;
}
2.缓存策略
b.DiskLruCache(磁盘缓存)
使用方法:
1.计算分配DiskLruCache的容量
2.设置缓存目录
3.创建DiskLruCache对象 注意不能通过构造方法来创建 而是提供open()方法;
4.利用Editor,SnapShot和remove()实现数据的添加,获取和删除
5.调用flush()将数据写入磁盘
DiskLruCache的创建:
其中参数含义:
a.directory:磁盘缓存的存储路径 有两种目录:
SD上的缓存目录:/sdcard/Android/daa/package_name/cache目录,当应用被卸载后会被删除
其他目录:应用卸载后缓存数据还在。
b.appVersion:当前应用的版本号 一般设为1.
c.valueCount:单个节点所对应的数据的个数 一般设为1
d.maxSize:缓存的总大小 超出这个设定值后DisckLruCache会清除一些缓存
第一行:libcore.io.DiskLruCache固定写死
第二行:DiskLruCache版本号
第三行:App版本号 由open()方法的参数appVersion传入
第四行:同一个key对应多少文件,由open()方法的参数valueCount传入 一般为1
第五行:空格
第六行:以DIRTY开头 后面跟着的是图片的key值 表示准备缓存这张图片 当调用DiskLruCache的edit()时就会生成这行记录
第七行:以Clean开头,后面跟着的是图片的key值和大小,当调用editor.commit()时会生成这条记录,表示缓存成功;如果调用editor.abort()表示缓存失败,则会生成Remove开头的表示删除这条数据。