缓存
Android开发中,如果每次访问资源都通过网络访问会导致流量使用和速度慢的情况
对于图片或者另外大的资源的加载(视频,音频),使用缓存就很有必要
两种缓存方法
首先缓存到存储设备上,这样下次加载资源时就不需要使用网络,其次可以缓存到内存中,从内存中加载的速度要高于从存储设备中加载
所谓的二级缓存就是指即有内存缓存又有存储设备缓存
官方提供了LruCache和DiskLruCache,分别用于内存缓存和存储设备缓存
Lru:Least Recently Used 最近最少使用算法,这种算法的核心思想是缓存快达到预设值时,优先淘汰最少使用的缓存目标
LruCache示例代码
int maxMemory= (int) (Runtime.getRuntime().maxMemory()/1024);
int cacheSize=maxMemory/8;
LruCache<String,Bitmap> lruCache=new LruCache<String,Bitmap>(cacheSize){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight()/1024;
}
};
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.icon_wallet_x);
lruCache.put("abc",bitmap);
lruCache.get("abc");
lruCache.remove("abc");
这里取进程可用最大内存的1/8来做缓存可用大小,单位设为KB
在sizeOf方法中提供单个缓存目标的大小的计算方法
还可以覆写entryRemoved方法,在LruCache移除旧缓存时调用
put,get,remove对应添加,获取,移除
DiskLruCache
DiskLruCache被官方推荐但没有在官方SDK中提供,需要自己去添加依赖
https://github.com/JakeWharton/DiskLruCache
open()创建对象
四个参数:第一个参数文件存储路径,第二个版本号(传1就行),第三个单个节点对应数据个数(传1就行),第四个参数缓存的可用大小
edit(key)获取DiskLruCache.Editor对象,editor.newOutputStream获取字节输出流对象
文件写入完成要editor.commit()提交,文件写入异常可以通过editor.abort()回退
get(key)获取DiskLruCache.Snapshot对象,snapshot.getInputStream()获取字节输入流对象
remove(key)移除指定缓存delete()清空缓存并且关闭close()关闭缓存flush()强制缓存操作写入文件系统
size()得到当前缓存大小getMaxSize()获取缓存最大存储大小
注意点:
key的格式要求: [a-z0-9_-]{1,120}
close()之后就不能调用DiskLruCache的任何方法了,一般放在onDestroy()中
remove(key)之后要flush(),否则之后size()获取缓存使用大小会出现问题
示例代码:
public class Main7Activity extends AppCompatActivity {
private DiskLruCache diskLruCache;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main7);
String url="http://f.hiphotos.baidu.com/image/pic/item/b7fd5266d016092446517fdadd0735fae7cd34ff.jpg";
String key="abc";
String key2="adfafafadf";
String key3="zzzzzzzzzz";
try {
diskLruCache=getDiskLruCache("testDiskLruCache");
// saveDiskData(diskLruCache,key,key.getBytes());
// saveDiskData(diskLruCache,key2,key2.getBytes());
// saveDiskData(diskLruCache,key3,key3.getBytes());
// System.out.println(new String(getDiskData(diskLruCache,key)));
// System.out.println(new String(getDiskData(diskLruCache,key2)));
// System.out.println(new String(getDiskData(diskLruCache,key3)));
// removeDiskData(diskLruCache,key);
// removeDiskData(diskLruCache,key2);
// removeDiskData(diskLruCache,key3);
// clearDiskData(diskLruCache);
System.out.println(getDiskDataSize(diskLruCache));
System.out.println(diskLruCache.getMaxSize());
} catch (IOException e) {
e.printStackTrace();
}
}
//获取DiskLruCache对象,第一次参数为文件路径名
public DiskLruCache getDiskLruCache(String fileDirectory) throws IOException {
long size=1024*1024*10;//10MB
DiskLruCache diskLruCache = null;
File diskCacheFile=new File(getCacheDir(),fileDirectory);
if (!diskCacheFile.exists()){
diskCacheFile.mkdir();
}
diskLruCache=DiskLruCache.open(diskCacheFile, 1,1,size);
return diskLruCache;
}
//根据key保存byte[] data数据
public void saveDiskData(final DiskLruCache diskLruCache, final String key, final byte[] data) {
new Thread(new Runnable() {
@Override
public void run() {
try {
DiskLruCache.Editor editor = null;
editor=diskLruCache.edit(key);
OutputStream outputStream=null;
if (editor!=null){
outputStream=editor.newOutputStream(0);
if (outputStream!=null){
outputStream.write(data);
outputStream.close();
editor.commit();
}
}
diskLruCache.flush();
System.out.println("data大小: "+data.length);
System.out.println("DiskLruCache大小: "+diskLruCache.size());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
//根据key获取byte[]数据
public byte[] getDiskData(DiskLruCache diskLruCache, String key) throws IOException {
DiskLruCache.Snapshot snapshot=diskLruCache.get(key);
System.out.println(snapshot.getLength(0));
InputStream inputStream= snapshot.getInputStream(0);
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
byte[] b=new byte[1024];
int len=0;
while ((len=inputStream.read(b))!=-1){
byteArrayOutputStream.write(b,0,len);
}
byteArrayOutputStream.flush();
inputStream.close();
return byteArrayOutputStream.toByteArray();
}
//清除指定key的数据
public void removeDiskData(DiskLruCache diskLruCache, String key) throws IOException {
diskLruCache.remove(key);
diskLruCache.flush();
}
//清空数据
public void clearDiskData(DiskLruCache diskLruCache) throws IOException {
diskLruCache.delete();
}
//获取缓存大小
public long getDiskDataSize(DiskLruCache diskLruCache){
return diskLruCache.size();
}
@Override
protected void onDestroy() {
super.onDestroy();
try {
diskLruCache.close();
} catch (IOException e) {
e.printStackTrace();
}
}
一个完整的网络请求+二级缓存的Bitmap图片加载轮子(自己写的只实现了基本功能,非常粗糙)