博客转移到个人站点:
http://www.wangchengmeng.club/2018/02/04/%E5%AE%9E%E7%8E%B0%E4%B8%89%E7%BA%A7%E7%BC%93%E5%AD%98/
欢迎来吐槽
三级缓存
1.思想:
1.从网络上获取数据,效率比较低,速度较慢,而且需要联网
2.为了更高的提高读取已经从网络上获取过的数据,并且在没联网的情况下也可以浏览,在第一次从网络上获取数据的时候将数据存储到缓存文件中
3.为了提高读取效率,直接从内存中读取是最快的,可以将获取的数据保存到内存中(LruCache),在内存足够的情况下,系统直接从内存中读取数据,效率是比较高的,当然,当内存不足的时候,系统会回收你在内存中保存在数据,这个时候你就需要从缓存文件中读取,如果缓存文件没有的情况下,你再从网络上获取。
2.优点
1.对于读取你已经从网络上读取过的数据,使用三级缓存,可以大大提高读取数据的效率,
2.在没有联网的情况下你仍可以读取你保存的数据
3.不必每次都需要从网络上去获取数据,只是第一次访问的时候需要访问网络,节省了流量
3.实现一个三级缓存图片的工具类
1.定义一个工具类 BitmapCacheUtils并实现其构造方法
public class BitmapCacheUtils {
private HomeActivity mContext;
private LruCache<String, Bitmap> lruCache;
private ExecutorService threadPool;
HashMap<ImageView,String> hm = new HashMap<ImageView,String>();
public BitmapCacheUtils(HomeActivity context) {
this.mContext = context;
int maxSize = (int) (Runtime.getRuntime().freeMemory() / 2); //运行的可用内存的一半
//线程池
threadPool = Executors.newFixedThreadPool(3);
//1级缓存的容器 软引用
//参数是你允许的最大缓存,你存储的数据不可以超过这个值,
lruCache = new LruCache<String, Bitmap>(maxSize){
@Override
protected int sizeOf(String key, Bitmap value) {
//动态计算每张图片的大小
return value.getRowBytes() * value.getHeight();
}
};
}
2.定义一个方法(根据传入的url给ImageView添加图片)
public void display(ImageView image, String url) {
// 首先从内存获取数据 内存有数据了 就不必去本地或者网络中获取了,提高效率
Bitmap bitmap = lruCache.get(url);
if(bitmap != null){
image.setImageBitmap(bitmap);
return;
}
// 从本地缓存文件中获取数据
Bitmap bitmap2 = getBitmapFromCache(url); ---》3.
if(bitmap2 != null){
//本地有数据了,就直接本地获取,不必去网络中获取了
image.setImageBitmap(bitmap2);
return ;
}
//获取之前先将url存储在hashMap中
hm.put(image, url);
// 从网络获取数据
getDataFromNet(image, url); ---》4.
}
3.从本地读取图片的时候,如果读取有数据,也将其保存到内存中
private Bitmap getBitmapFromCache(String url){
//http://www.baidu.com/mm.png url类似这钟,/在文件中是会影响到路径的读取,所以截取最后一个/后面的字符作为文件名
File file = new File(mContext.getCacheDir(),url.substring(url.lastIndexOf("/") + 1));
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
if(bitmap != null){
//如果本地有文件 在内存中保存一份
lruCache.put(url, bitmap);
}
return bitmap;
}
4.从网络中读取数据(耗时操作放在子线程中执行)
private void getDataFromNet(ImageView image, String url) {
//线程池提交任务 使用线程池 提高效率
threadPool.submit(new Task(image,url));
}
//线程执行的任务类
private class Task implements Runnable{
public ImageView img;
public String url;
public Task(ImageView img ,String url){
this.img = img;
this.url = url;
}
@Override
public void run() {
getFromNet(img, url); ---》5.
}
}
5.联网获取图片
protected void getFromNet(final ImageView image, final String url) {
try {
URL cacheUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) cacheUrl
.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
connection.connect();
int code = connection.getResponseCode();
if (code == 200) {
// 请求成功
InputStream is = connection.getInputStream();
final Bitmap bitmap = BitmapFactory.decodeStream(is);
// 往内存写入数据
lruCache.put(url, bitmap); ---》6.
// 往本地写数据
write2Local(bitmap, url); ----》7.
//子线程中不可以更新UI
mContext.runOnUiThread(new Runnable() {
@Override
public void run() {
//在设置图片的时候,判断绑定的url是否是新的
if(hm.get(image).equals(url)){
//是新的url那就可以进行绑定了
image.setImageBitmap(bitmap);
}
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
6.往内存中写入数据
// 往内存写入数据
lruCache.put(url, bitmap);
主要是 LruCache这个类
实例化:
int maxSize = (int) (Runtime.getRuntime().freeMemory() / 2); //运行的可用内存的一半
//1级缓存的容器 软引用
//参数是你允许的最大缓存,你存储的数据不可以超过这个值,
lruCache = new LruCache<String, Bitmap>(maxSize){
@Override
protected int sizeOf(String key, Bitmap value) {
//动态计算每张图片的大小
return value.getRowBytes() * value.getHeight();
}
};
7.往本地写入数据
protected void write2Local(Bitmap bitmap, String url) {
// 缓存文件
File cacheDir = mContext.getCacheDir();
File file = new File(cacheDir, url.substring(url.lastIndexOf("/") + 1));
try {
// 写入图片
bitmap.compress(CompressFormat.PNG, 100,
new FileOutputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}