您的位置:首页 > 理论基础 > 计算机网络

实现三级缓存

2015-10-17 22:22 597 查看
博客转移到个人站点:

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();
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息