Acache缓存的使用

来源:互联网 发布:app程序员招聘要求 编辑:程序博客网 时间:2024/05/18 17:26

  最近做app开发时,使用了Acache缓存来实现从网络中的图片,文本数据进行在本地存储,Android通过使用二级缓存来减少频繁的网络操作,减少流量,提升app使用的性能。

可以缓存字符串,JsonObject,,JsonArray,Bitmap,Drawable,序列化的java对象,和byte数据转化。

查阅相资料了解到Acache缓存 的特点:

1.轻量化,

2.可配置,包括配置缓存路径,缓存大小,缓存数量等。

3.可以设置缓存超时时间,缓存超时是自动失效,并被删除。

4.支持多线程

 会在下文中会结合源码进行分析。

在阅读Acache源码时,使用这种数据

package com.codeest.geeknews.component;   import android.content.Contextimport android.graphics.Bitmapimport android.graphics.BitmapFactoryimport android.graphics.Canvasimport android.graphics.PixelFormatimport android.graphics.drawable.BitmapDrawableimport android.graphics.drawable.Drawable;   import com.codeest.geeknews.app.Constants;   import org.json.JSONArrayimport org.json.JSONObject;   import java.io.BufferedReaderimport java.io.BufferedWriterimport java.io.ByteArrayInputStreamimport java.io.ByteArrayOutputStreamimport java.io.Fileimport java.io.FileOutputStreamimport java.io.FileReaderimport java.io.FileWriterimport java.io.IOExceptionimport java.io.ObjectInputStreamimport java.io.ObjectOutputStreamimport java.io.RandomAccessFileimport java.io.Serializableimport java.math.BigDecimalimport java.util.Collectionsimport java.util.HashMapimport java.util.Mapimport java.util.Map.Entryimport java.util.Setimport java.util.concurrent.atomic.AtomicIntegerimport java.util.concurrent.atomic.AtomicLong;   /** * @author Michael Yang(www.yangfuhai.com) update at 2013.08.07 */ public class ACachepublic static final int TIME_HOUR = 60 * 60public static final int TIME_DAY = TIME_HOUR * 24private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb private static final int MAX_COUNT = Integer.MAX_VALUE;// 不限制存放数据的数量 private static Map<String,ACache> mInstanceMap=new HashMap<String,ACache>(); private ACacheManager mCache;   Acache缓存get基本方法//其中三个get方法是关联的,首先调用get(Context ctx),然后到get(Contextt ctx,String cachename)//最后到get(Context ctx,long size,mex_count) public static ACache get(Context ctx) { return get(ctx, "Data"); }     public static ACache get(Context ctx, String cacheName) { File f = new File(Constants.PATH_DATA, cacheName); return get(f, MAX_SIZE, MAX_COUNT); }     public static ACache get(File cacheDir) { return get(cacheDir, MAX_SIZE, MAX_COUNT); }     public static ACache get(Context ctx, long max_zise, int max_count) { File f = new File(Constants.PATH_DATA,"Data"); return get(f, max_zise, max_count); }  //新建缓存实例,存入实例map,key为缓存目录+每次应用开启的进程id public static ACache get(File cacheDir, long max_zise, int max_count) { //返回key为缓存目录+每次应用开启的进程id的map的value值,付给缓存实例manager ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile()+ myPid()); if (manager == null) {//初次运行时,当manager为空时,通过Acache构建实例,然后将该实例引用存入mInstanceMap中 manager = new ACache(cacheDir, max_zise, max_count); mInstanceMap.put(cacheDir.getAbsolutePath()+ myPid(), manager); } return manager; }   public static boolean deleteDir(File dir) { if (dir != null && dir.isDirectory()) { String[] children = dir.list(); for (String aChildren: children) { boolean success = deleteDir(new File(dir, aChildren)); if (!success) { return false; } } } assert dir != nullreturn dir.delete(); }   public static String getCacheSize(File file) { return getFormatSize(getFolderSize(file)); }   public static long getFolderSize(Filefile) { long size = 0tryFile[] fileList = file.listFiles(); for (File aFileList: fileList) { // 如果下面还有文件 if (aFileList.isDirectory()) { size = size + getFolderSize(aFileList); } else { size = size + aFileList.length(); } } } catch (Exception e) { e.printStackTrace(); } return size; }   public static String getFormatSize(doublesize) { double kiloByte = size / 1024if (kiloByte < 1) { // return size + "Byte"; return "0K"; }   double megaByte = kiloByte / 1024if (megaByte < 1) { BigDecimal result1 = new BigDecimal(Double.toString(kiloByte)); return result1.setScale(2,BigDecimal.ROUND_HALF_UP) .toPlainString() + "KB"; }   double gigaByte = megaByte / 1024if (gigaByte < 1) { BigDecimal result2 = new BigDecimal(Double.toString(megaByte)); return result2.setScale(2,BigDecimal.ROUND_HALF_UP) .toPlainString() + "MB"; }   double teraBytes = gigaByte / 1024if (teraBytes < 1) { BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); return result3.setScale(2,BigDecimal.ROUND_HALF_UP) .toPlainString() + "GB"; } BigDecimal result4 = new BigDecimal(teraBytes); return result4.setScale(2,BigDecimal.ROUND_HALF_UP).toPlainString() + "TB"; }     private static String myPid() { return "_"+android.os.Process.myPid(); }     private ACache(File cacheDir, long max_size, int max_count) { if (!cacheDir.exists()&&!cacheDir.mkdirs()) { throw new RuntimeException("can't make dirs in"+ cacheDir.getAbsolutePath()); } mCache = new ACacheManager(cacheDir, max_size, max_count); }   // ======================================= // ============ String数据 读写 ============== // =======================================     /** * 保存 String数据 到 缓存中 * * @param key 保存的key * @param value 保存的String数据 */ public void put(Stringkey,String value) { File file = mCache.newFile(key); BufferedWriter out = nulltry { out = new BufferedWriter(newFileWriter(file),1024); out.write(value); } catch (IOException e) { e.printStackTrace(); } finallyif (out != null) { try { out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } mCache.put(file); } }     /** * 保存 String数据 到 缓存中 * * @param key 保存的key * @param value 保存的String数据 * @param saveTime 保存的时间,单位:秒 */ public void put(Stringkey,String value, int saveTime) { put(key, Utils.newStringWithDateInfo(saveTime, value)); }     /** * 读取 String数据 * * @return String 数据 */ public String getAsString(Stringkey) { File file = mCache.get(key); if (!file.exists())returnnullboolean removeFile = falseBufferedReader in = nulltry { in = new BufferedReader(newFileReader(file)); String readString = ""String currentLine; while ((currentLine = in.readLine()) != null) { readString += currentLine; } if (!Utils.isDue(readString)) { return Utils.clearDateInfo(readString); } else { removeFile = truereturn null; } } catch (IOException e) { e.printStackTrace(); return null; } finallyif (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (removeFile) remove(key); } }   // ======================================= // ============= JSONObject 数据 读写 ============== // =======================================     /** * 保存 JSONObject数据 到 缓存中 * @param key 保存的key * @param value 保存的JSON数据 */ public void put(Stringkey,JSONObject value) { put(key, value.toString()); }     /** * 保存 JSONObject数据 到 缓存中 * * @param key 保存的key * @param value 保存的JSONObject数据 * @param saveTime 保存的时间,单位:秒 */ public void put(Stringkey,JSONObject value, int saveTime) { put(key, value.toString(), saveTime); }     /** * 读取JSONObject数据 * * @return JSONObject数据 */ public JSONObject getAsJSONObject(Stringkey) { String JSONString = getAsString(key); tryJSONObject obj = new JSONObject(JSONString); return obj; } catch (Exception e) { e.printStackTrace(); return null; } }   // ======================================= // ============ JSONArray 数据 读写 ============= // =======================================     /** * 保存 JSONArray数据 到 缓存中 * * @param key 保存的key * @param value 保存的JSONArray数据 */ public void put(Stringkey,JSONArray value) { put(key, value.toString()); }     /** * 保存 JSONArray数据 到 缓存中 * * @param key 保存的key * @param value 保存的JSONArray数据 * @param saveTime 保存的时间,单位:秒 */ public void put(Stringkey,JSONArray value, int saveTime) { put(key, value.toString(), saveTime); }     /** * 读取JSONArray数据 * * @return JSONArray数据 */ public JSONArray getAsJSONArray(Stringkey) { String JSONString = getAsString(key); tryJSONArray obj = new JSONArray(JSONString); return obj; } catch (Exception e) { e.printStackTrace(); return null; } }   // ======================================= // ============== byte 数据 读写 ============= // =======================================     /** * 保存 byte数据 到 缓存中 * * @param key 保存的key * @param value 保存的数据 */ public void put(Stringkey,byte[] value) { File file = mCache.newFile(key); FileOutputStream out = nulltry { out = new FileOutputStream(file); out.write(value); } catch (Exception e) { e.printStackTrace(); } finallyif (out != null) { try { out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } mCache.put(file); } }     /** * 保存 byte数据 到 缓存中 * * @param key 保存的key * @param value 保存的数据 * @param saveTime 保存的时间,单位:秒 */ public void put(Stringkey,byte[] value, int saveTime) { put(key, Utils.newByteArrayWithDateInfo(saveTime, value)); }     /** * 获取 byte 数据 * * @return byte 数据 */ public byte[] getAsBinary(Stringkey) { RandomAccessFile RAFile = nullboolean removeFile = falsetryFile file = mCache.get(key); if (!file.exists())returnnullRAFile = new RandomAccessFile(file, "r"); byte[] byteArray = new byte[(int) RAFile.length()]; RAFile.read(byteArray); if (!Utils.isDue(byteArray)) { return Utils.clearDateInfo(byteArray); } else { removeFile = truereturn null; } } catch (Exception e) { e.printStackTrace(); return null; } finallyif (RAFile!=null) { tryRAFile.close(); } catch (IOException e) { e.printStackTrace(); } } if (removeFile) remove(key); } }   // ======================================= // ============= 序列化 数据 读写 =============== // =======================================     /** * 保存 Serializable数据 到 缓存中 * * @param key 保存的key * @param value 保存的value */ public void put(Stringkey,Serializable value) { put(key, value, -1); }     /** * 保存 Serializable数据到 缓存中 * * @param key 保存的key * @param value 保存的value * @param saveTime 保存的时间,单位:秒 */ public void put(Stringkey,Serializable value,int saveTime) { ByteArrayOutputStream baos=nullObjectOutputStream oos = nulltry { baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(value); byte[] data = baos.toByteArray(); if (saveTime != -1) { put(key, data, saveTime); } else { put(key, data); } } catch (Exception e) { e.printStackTrace(); } finallytry { oos.close(); } catch (IOException e) { } } }     /** * 读取 Serializable数据 * * @return Serializable 数据 */ public Object getAsObject(Stringkey) { byte[] data = getAsBinary(key); if (data != null) { ByteArrayInputStream bais=nullObjectInputStream ois = nulltry { bais = new ByteArrayInputStream(data); ois = new ObjectInputStream(bais); Object reObject = ois.readObject(); return reObject; } catch (Exception e) { e.printStackTrace(); return null; } finallytryif (bais != null) bais.close(); } catch (IOException e) { e.printStackTrace(); } tryif (ois != null) ois.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; }   // ======================================= // ============== bitmap 数据 读写 ============= // =======================================     /** * 保存 bitmap 到 缓存中 * * @param key 保存的key * @param value 保存的bitmap数据 */ public void put(Stringkey,Bitmap value) { put(key, Utils.Bitmap2Bytes(value)); }     /** * 保存 bitmap 到 缓存中 * * @param key 保存的key * @param value 保存的 bitmap 数据 * @param saveTime 保存的时间,单位:秒 */ public void put(Stringkey,Bitmap value, int saveTime) { put(key, Utils.Bitmap2Bytes(value), saveTime); }     /** * 读取 bitmap 数据 * * @return bitmap 数据 */ public Bitmap getAsBitmap(Stringkey) { if (getAsBinary(key) == null) { return null; } return Utils.Bytes2Bimap(getAsBinary(key)); }   // ======================================= // ============= drawable 数据 读写 ============= // =======================================     /** * 保存 drawable 到 缓存中 * * @param key 保存的key * @param value 保存的drawable数据 */ public void put(Stringkey,Drawable value) { put(key, Utils.drawable2Bitmap(value)); }     /** * 保存 drawable 到 缓存中 * * @param key 保存的key * @param value 保存的 drawable 数据 * @param saveTime 保存的时间,单位:秒 */ public void put(Stringkey,Drawable value, int saveTime) { put(key, Utils.drawable2Bitmap(value), saveTime); }     /** * 读取 Drawable 数据 * * @return Drawable 数据 */ public Drawable getAsDrawable(Stringkey) { if (getAsBinary(key) == null) { return null; } return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key))); }     /** * 获取缓存文件 * * @return value 缓存的文件 */ public File file(Stringkey) { File f = mCache.newFile(key); if (f.exists())return f; return null; }     /** * 移除某个key * * @return 是否移除成功 */ public boolean remove(Stringkey) { return mCache.remove(key); }     /** * 清除所有数据 */ public void clear() { mCache.clear(); }       * @title 缓存管理器 */ public class ACacheManagerprivate final AtomicLong cacheSize; private final AtomicInteger cacheCount; private final long sizeLimit; private final int countLimit; private final Map<File,Long> lastUsageDates=Collections.synchronizedMap(newHashMap<File,Long>()); protected File cacheDir;     private ACacheManager(FilecacheDir,long sizeLimit, int countLimit) { this.cacheDir= cacheDir; this.sizeLimit= sizeLimit; this.countLimit= countLimit; cacheSize = new AtomicLong(); cacheCount = new AtomicInteger(); calculateCacheSizeAndCacheCount(); }     /** * 计算 cacheSize和cacheCount */ private void calculateCacheSizeAndCacheCount() { new Thread(new Runnable() { @Override public void run() { int size = 0int count = 0File[] cachedFiles = cacheDir.listFiles(); if (cachedFiles != null) { for (File cachedFile: cachedFiles) { size += calculateSize(cachedFile); count += 1; lastUsageDates.put(cachedFile, cachedFile.lastModified()); } cacheSize.set(size); cacheCount.set(count); } } }).start(); }     private void put(Filefile) { int curCacheCount = cacheCount.get(); while (curCacheCount + 1 > countLimit) { long freedSize = removeNext(); cacheSize.addAndGet(-freedSize);   curCacheCount = cacheCount.addAndGet(-1); } cacheCount.addAndGet(1);   long valueSize = calculateSize(file); long curCacheSize = cacheSize.get(); while (curCacheSize + valueSize > sizeLimit) { long freedSize = removeNext(); curCacheSize = cacheSize.addAndGet(-freedSize); } cacheSize.addAndGet(valueSize);   Long currentTime = System.currentTimeMillis(); file.setLastModified(currentTime); lastUsageDates.put(file, currentTime); }     private File get(Stringkey) { File file = newFile(key); Long currentTime = System.currentTimeMillis(); file.setLastModified(currentTime); lastUsageDates.put(file, currentTime);   return file; }     private File newFile(Stringkey) { return new File(cacheDir, key.hashCode()+""); }     private boolean remove(Stringkey) { File image = get(key); return image.delete(); }     private void clear() { lastUsageDates.clear(); cacheSize.set(0); File[] files = cacheDir.listFiles(); if (files != null) { for (File f: files) { f.delete(); } } }     /** * 移除旧的文件 */ private long removeNext() { if (lastUsageDates.isEmpty()) { return 0; }   Long oldestUsage = nullFile mostLongUsedFile = nullSet<Entry<File,Long>> entries= lastUsageDates.entrySet(); synchronized (lastUsageDates) { for (Entry<File,Long> entry: entries) { if (mostLongUsedFile == null) { mostLongUsedFile = entry.getKey(); oldestUsage = entry.getValue(); } elseLong lastValueUsage = entry.getValue(); if (lastValueUsage < oldestUsage) { oldestUsage = lastValueUsage; mostLongUsedFile = entry.getKey(); } } } }   long fileSize = calculateSize(mostLongUsedFile); if (mostLongUsedFile.delete()) { lastUsageDates.remove(mostLongUsedFile); } return fileSize; }     private long calculateSize(Filefile) { return file.length(); } }   /** * @author 杨福海(michael) www.yangfuhai.com * @version 1.0 * @title 时间计算工具类 */ private static class Utils {   /** * 判断缓存的String数据是否到期 * * @return true:到期了 false:还没有到期 */ private static boolean isDue(String str) { return isDue(str.getBytes()); }     /** * 判断缓存的byte数据是否到期 * * @return true:到期了 false:还没有到期 */ private static boolean isDue(byte[] data) { String[] strs = getDateInfoFromDate(data); if (strs != null && strs.length == 2) { String saveTimeStr = strs[0]; while (saveTimeStr.startsWith("0")) { saveTimeStr = saveTimeStr.substring(1, saveTimeStr.length()); } long saveTime = Long.valueOf(saveTimeStr); long deleteAfter = Long.valueOf(strs[1]); if (System.currentTimeMillis()> saveTime+ deleteAfter * 1000) { return true; } } return false; }     private static String newStringWithDateInfo(intsecond,String strInfo) { return createDateInfo(second)+ strInfo; }     private static byte[] newByteArrayWithDateInfo(intsecond,byte[] data2) { byte[] data1 = createDateInfo(second).getBytes(); byte[] retdata = new byte[data1.length + data2.length]; System.arraycopy(data1,0, retdata,0, data1.length); System.arraycopy(data2,0, retdata, data1.length, data2.length); return retdata; }     private static String clearDateInfo(StringstrInfo) { if (strInfo != null && hasDateInfo(strInfo.getBytes())) { strInfo = strInfo.substring(strInfo.indexOf(mSeparator)+1, strInfo.length()); } return strInfo; }     private static byte[] clearDateInfo(byte[]data) { if (hasDateInfo(data)) { return copyOfRange(data, indexOf(data, mSeparator)+1, data.length); } return data; }     private static boolean hasDateInfo(byte[] data) { return data != null && data.length > 15 && data[13] == '-'&& indexOf(data, mSeparator)>14; }     private static String[] getDateInfoFromDate(byte[]data) { if (hasDateInfo(data)) { String saveDate = new String(copyOfRange(data, 0, 13)); String deleteAfter = new String(copyOfRange(data, 14, indexOf(data, mSeparator))); return new String[] { saveDate, deleteAfter }; } return null; }  // private static int indexOf(byte[] data, char c) { for (int i=0; i < data.length; i++) { if (data[i] == c) { return i; } } return -1; }   //时间上 private static byte[] copyOfRange(byte[] original, int from, int to) { int newLength = to - from; if (newLength < 0) throw new IllegalArgumentException(from + " >"+ to); byte[] copy = new byte[newLength]; System.arraycopy(original, from, copy,0,Math.min(original.length- from, newLength)); return copy; }     private static final char mSeparator = ' ';     private static String createDateInfo(int second) { String currentTime = System.currentTimeMillis()+""while (currentTime.length()<13) { currentTime = "0"+ currentTime; } return currentTime + "-"+ second+ mSeparator; }     /* * Bitmap → byte[] */ private static byte[] Bitmap2Bytes(Bitmapbm) { if (bm == null) { return null; } ByteArrayOutputStream baos=new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.PNG,100, baos); return baos.toByteArray(); }     /*将byte数据转化为bitmap * byte[] → Bitmap */ private static Bitmap Bytes2Bimap(byte[] b) { if (b.length==0) { return null; } return BitmapFactory.decodeByteArray(b,0, b.length); }     /* 把drawable转化为bitmap数据 * Drawable → Bitmap */ private static Bitmap drawable2Bitmap(Drawabledrawable) { if (drawable == null) { return null; } // 取 drawable 的长宽 int w = drawable.getIntrinsicWidth(); int h = drawable.getIntrinsicHeight(); // 取 drawable 的颜色格式 Bitmap.Config config= drawable.getOpacity()!=PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565// 建立对应 bitmap Bitmap bitmap = Bitmap.createBitmap(w, h, config); // 建立对应 bitmap 的画布 Canvas canvas = new Canvas(bitmap); drawable.setBounds(0,0, w, h); // 把 drawable 内容画到画布中 drawable.draw(canvas); return bitmap; }     /* * Bitmap → Drawable */ @SuppressWarnings("deprecation")privatestatic Drawable bitmap2Drawable(Bitmapbm) { if (bm == null) { return null; } return new BitmapDrawable(bm); } } }使用Acache来缓存网络请求数据,可以使app端本地可以先缓存http的发送过来的数据内容,比如设置缓存时间是1个小时,可以让用户不用频繁的去刷新内容,频繁加载数据,使用户流量消耗较大,并且频繁请求数据会降低app的性能。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 两个月不来月经了也没怀孕怎么办 婴儿不吃奶粉母乳又不够吃怎么办 怀孕39周了还没反应怎么办 脸过敏了又红又痒怎么办 刚开的淘宝店没生意怎么办 我22岁长得显老怎么办 卡的钱被qq转走怎么办 招行u盾密码忘了怎么办 孩子上五年级了成绩非常差怎么办 红米3s开不开机怎么办 皮肤被虫子咬了红肿痒怎么办 微信被骗了1万多怎么办 6个月宝宝吃了纸怎么办 农行k宝扣了50块怎么办 4g流量用的太快怎么办 怀疑老公有外遇最明智的怎么办 咽喉疼怎么办最简单的方法如下 生完孩子后腰疼的厉害怎么办 眼睛进东西了弄不出来怎么办 18k金不给换黄金怎么办 我22岁欠了10万怎么办 1岁宝宝又吐又拉怎么办 月经10天了还没干净怎么办 舌头有异味怎么办是有口臭吗 快8个月羊水破了怎么办 25岁欠了50万债怎么办 28岁血压高150低压110怎么办 苹果6的4g网络慢怎么办 一个月染了6次头怎么办 五0二干在衣服上怎么办 刚怀孕见红了肚子不痛怎么办 我有外遇了老婆不离婚怎么办 套了牙套的牙疼怎么办 我鼻子上有很多螨虫和黑头怎么办 鱼刺卡在喉咙怎么办最有效的办法 脚被蚊子咬了很痒怎么办 好压7z密码忘了怎么办 4g卡显示2g网络怎么办 过塑机把纸吞了怎么办 红米1s开不了机怎么办 跟老婆吵架闹的要离婚该怎么办