android轻量级缓存框架ASimpleCache分析

转自:http://blog.csdn.net/superjunjin/article/details/45096805

框架地址

https://github.com/yangfuhai/ASimpleCache  此框架作者为大名鼎鼎的afinal作者

官方简介:

ASimpleCache 是一个为android制定的 轻量级的 开源缓存框架。轻量到只有一个java文件(由十几个类精简而来)。

有个问题是作者所说的自动失效,其实是在获取数据时判断存入缓存的数据是否过期,如果过期,则删除数据缓存,返回null。当然,如果真正的自动删除,应该只能开启服务,不断判断是否过期来删除吧,也没有必要


--------------------------------------------------------------------------------


1、它可以缓存什么东西?
普通的字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 byte数据。

2、它有什么特色?
特色主要是:
1:轻,轻到只有一个JAVA文件。
2:可配置,可以配置缓存路径,缓存大小,缓存数量等。
3:可以设置缓存超时时间,缓存超时自动失效,并被删除。
4:支持多进程。
3、它在android中可以用在哪些场景?
1、替换SharePreference当做配置文件
2、可以缓存网络请求数据,比如oschina的android客户端可以缓存http请求的新闻内容,缓存时间假设为1个小时,超时后自动失效,让客户端重新请求新的数据,减少客户端流量,同时减少服务器并发量。
3、您来说...
4、如何使用 ASimpleCache?
以下有个小的demo,希望您能喜欢:

ACache mCache = ACache.get(this);
mCache.put("test_key1", "test value");
mCache.put("test_key2", "test value", 10);//保存10秒,如果超过10秒去获取这个key,将为null
mCache.put("test_key3", "test value", 2 * ACache.TIME_DAY);//保存两天,如果超过两天去获取这个key,将为null
获取数据

ACache mCache = ACache.get(this);
String value = mCache.getAsString("test_key1");
更多示例请见Demo

关于作者michael
屌丝程序员一枚,喜欢开源。
个人博客:
http://www.yangfuhai.com
交流QQ群 : 192341294(已满) 246710918(未满)

主要分析下集万千宠爱于一身的ACache类吧(以字符串存储为例)

一,首先先要创建缓存

get(Context ctx, String cacheName)方法新建缓存目录

get(File cacheDir, long max_zise, int max_count)方法新建缓存实例,存入实例map,key为缓存目录加上每次应用开启的进程id

  1. public static ACache get(Context ctx) {  
  2.         return get(ctx, "ACache");  
  3.     }  
  4.   
  5.     public static ACache get(Context ctx, String cacheName) {  
  6.         //新建缓存目录  
  7.         ///data/data/com.yangfuhai.asimplecachedemo/cache/ACache  
  8.         File f = new File(ctx.getCacheDir(), cacheName);  
  9.         return get(f, MAX_SIZE, MAX_COUNT);  
  10.     }  
  11.   
  12.     public static ACache get(File cacheDir) {  
  13.         return get(cacheDir, MAX_SIZE, MAX_COUNT);  
  14.     }  
  15.   
  16.     public static ACache get(Context ctx, long max_zise, int max_count) {  
  17.         File f = new File(ctx.getCacheDir(), "ACache");  
  18.         return get(f, max_zise, max_count);  
  19.     }  
  20.   
  21.     public static ACache get(File cacheDir, long max_zise, int max_count) {  
  22.         ///data/data/com.yangfuhai.asimplecachedemo/cache/ACache  
  23.         ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid());  
  24.         if (manager == null) {  
  25.             manager = new ACache(cacheDir, max_zise, max_count);  
  26.             //{/data/data/com.yangfuhai.asimplecachedemo/cache/ACache_4137=org.afinal.simplecache.ACache@2bc38270}  
  27.             //{/data/data/com.yangfuhai.asimplecachedemo/cache/ACache_12189=org.afinal.simplecache.ACache@2bc3d890}  
  28.             mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager);  
  29.         }  
  30.         return manager;  
  31.     }  
  32.   
  33.     private static String myPid() {  
  34.         return "_" + android.os.Process.myPid();  
  35.     }  
  36.   
  37.     private ACache(File cacheDir, long max_size, int max_count) {  
  38.         if (!cacheDir.exists() && !cacheDir.mkdirs()) {  
  39.             throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath());  
  40.         }  
  41.         mCache = new ACacheManager(cacheDir, max_size, max_count);  
  42.     }  


 

二,存入数据

put(String key, String value)方法写数据到文件

put(String key, String value)方法中的mCache.put(file)方法做了如下设置

文件放入程序缓存后,统计缓存总量,总数,文件存放到文件map中(value值为文件最后修改时间,便于根据设置的销毁时间进行销毁)
缓存没有超过限制,则增加缓存总量,总数的数值
缓存超过限制,则减少缓存总量,总数的数值
通过removeNext方法找到最老文件的大小

  1. public void put(String key, String value) {  
  2.         File file = mCache.newFile(key);  
  3.         BufferedWriter out = null;  
  4.         try {  
  5.             out = new BufferedWriter(new FileWriter(file), 1024);  
  6.             out.write(value);  
  7.         } catch (IOException e) {  
  8.             e.printStackTrace();  
  9.         } finally {  
  10.             if (out != null) {  
  11.                 try {  
  12.                     out.flush();  
  13.                     out.close();  
  14.                 } catch (IOException e) {  
  15.                     e.printStackTrace();  
  16.                 }  
  17.             }  
  18.             mCache.put(file);  
  19.         }  
  20.     }  
  1. //文件放入程序缓存后,统计缓存总量,总数,文件存放到文件map中(value值为文件最后修改时间,便于根据设置的销毁时间进行销毁)  
  2. //缓存没有超过限制,则增加缓存总量,总数的数值  
  3. //缓存超过限制,则减少缓存总量,总数的数值  
  4. //通过removeNext方法找到最老文件的大小  
  5. private void put(File file) {  
  6.     int curCacheCount = cacheCount.get();  
  7.     while (curCacheCount + 1 > countLimit) {  
  8.         long freedSize = removeNext();  
  9.         cacheSize.addAndGet(-freedSize);  
  10.   
  11.         curCacheCount = cacheCount.addAndGet(-1);  
  12.     }  
  13.     cacheCount.addAndGet(1);  
  14.   
  15.     long valueSize = calculateSize(file);  
  16.     long curCacheSize = cacheSize.get();  
  17.     while (curCacheSize + valueSize > sizeLimit) {  
  18.         long freedSize = removeNext();  
  19.         curCacheSize = cacheSize.addAndGet(-freedSize);  
  20.     }  
  21.     cacheSize.addAndGet(valueSize);  
  22.   
  23.     Long currentTime = System.currentTimeMillis();  
  24.     file.setLastModified(currentTime);  
  25.     lastUsageDates.put(file, currentTime);  
  26. }  


 

  1. /** 
  2.          * 移除旧的文件(冒泡,找到最后修改时间最小的文件) 
  3.          *  
  4.          * @return 
  5.          */  
  6.         private long removeNext() {  
  7.             if (lastUsageDates.isEmpty()) {  
  8.                 return 0;  
  9.             }  
  10.   
  11.             Long oldestUsage = null;  
  12.             File mostLongUsedFile = null;  
  13.             Set<Entry<File, Long>> entries = lastUsageDates.entrySet();  
  14.             synchronized (lastUsageDates) {  
  15.                 for (Entry<File, Long> entry : entries) {  
  16.                     if (mostLongUsedFile == null) {  
  17.                         mostLongUsedFile = entry.getKey();  
  18.                         oldestUsage = entry.getValue();  
  19.                     } else {  
  20.                         Long lastValueUsage = entry.getValue();  
  21.                         if (lastValueUsage < oldestUsage) {  
  22.                             oldestUsage = lastValueUsage;  
  23.                             mostLongUsedFile = entry.getKey();  
  24.                         }  
  25.                     }  
  26.                 }  
  27.             }  
  28.   
  29.             long fileSize = calculateSize(mostLongUsedFile);  
  30.             if (mostLongUsedFile.delete()) {  
  31.                 lastUsageDates.remove(mostLongUsedFile);  
  32.             }  
  33.             return fileSize;  
  34.         }  


三,获取数据

getAsString(String key)方法从缓存文件中读取数据,其中通过Utils.isDue(readString)方法判断数据是否过期,是否要删除

  1. public String getAsString(String key) {  
  2.         ///data/data/com.yangfuhai.asimplecachedemo/cache/ACache/1727748931  
  3.         File file = mCache.get(key);  
  4.         if (!file.exists())  
  5.             return null;  
  6.         boolean removeFile = false;  
  7.         BufferedReader in = null;  
  8.         try {  
  9.             in = new BufferedReader(new FileReader(file));  
  10.             String readString = "";  
  11.             String currentLine;  
  12.             while ((currentLine = in.readLine()) != null) {  
  13.                 readString += currentLine;  
  14.             }  
  15.             if (!Utils.isDue(readString)) {  
  16.                 return Utils.clearDateInfo(readString);  
  17.             } else {  
  18.                 removeFile = true;  
  19.                 return null;  
  20.             }  
  21.         } catch (IOException e) {  
  22.             e.printStackTrace();  
  23.             return null;  
  24.         } finally {  
  25.             if (in != null) {  
  26.                 try {  
  27.                     in.close();  
  28.                 } catch (IOException e) {  
  29.                     e.printStackTrace();  
  30.                 }  
  31.             }  
  32.             if (removeFile)  
  33.                 remove(key);  
  34.         }  
  35.     }  


 

  1. /** 
  2.          * 判断缓存的String数据是否到期 
  3.          *  
  4.          * @param str 
  5.          * @return true:到期了 false:还没有到期 
  6.          */  
  7.         private static boolean isDue(String str) {  
  8.             return isDue(str.getBytes());  
  9.         }  
  10.   
  11.         /** 
  12.          * 判断缓存的byte数据是否到期(到期:当前时间大于保存时间加上保存后的存留时间) 
  13.          *  
  14.          * @param data 
  15.          * @return true:到期了 false:还没有到期 
  16.          */  
  17.         private static boolean isDue(byte[] data) {  
  18.             String[] strs = getDateInfoFromDate(data);  
  19.             if (strs != null && strs.length == 2) {  
  20.                 String saveTimeStr = strs[0];  
  21.                 while (saveTimeStr.startsWith("0")) {  
  22.                     saveTimeStr = saveTimeStr.substring(1, saveTimeStr.length());  
  23.                 }  
  24.                 long saveTime = Long.valueOf(saveTimeStr);  
  25.                 long deleteAfter = Long.valueOf(strs[1]);  
  26.                 if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) {  
  27.                     return true;  
  28.                 }  
  29.             }  
  30.             return false;  
  31.         }  
  1. //数据有无存留时间设置  
  2.     private static boolean hasDateInfo(byte[] data) {  
  3.         return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14;  
  4.     }  
  5.        //saveDate文件保存时间毫秒数,deleteAfter文件保存后的保留时间毫秒数  
  6.     private static String[] getDateInfoFromDate(byte[] data) {  
  7.         if (hasDateInfo(data)) {  
  8.             String saveDate = new String(copyOfRange(data, 013));  
  9.             String deleteAfter = new String(copyOfRange(data, 14, indexOf(data, mSeparator)));  
  10.             return new String[] { saveDate, deleteAfter };  
  11.         }  
  12.         return null;  
  13.     }  


带注释的demo http://download.csdn.net/detail/superjunjin/8605307
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值