Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android輕量級緩存框架ASimpleCache分析

android輕量級緩存框架ASimpleCache分析

編輯:關於Android編程

 

官方簡介:

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

主要分析下集萬千寵愛於一身的ACache類吧(以字符串存儲為例)

一,首先先要創建緩存

get(Context ctx, String cacheName)方法新建緩存目錄

get(File cacheDir, long max_zise, int max_count)方法新建緩存實例,存入實例map,key為緩存目錄加上每次應用開啟的進程id

public static ACache get(Context ctx) {
		return get(ctx, ACache);
	}

	public static ACache get(Context ctx, String cacheName) {
		//新建緩存目錄
		///data/data/com.yangfuhai.asimplecachedemo/cache/ACache
		File f = new File(ctx.getCacheDir(), 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(ctx.getCacheDir(), ACache);
		return get(f, max_zise, max_count);
	}

	public static ACache get(File cacheDir, long max_zise, int max_count) {
		///data/data/com.yangfuhai.asimplecachedemo/cache/ACache
		ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid());
		if (manager == null) {
			manager = new ACache(cacheDir, max_zise, max_count);
			//{/data/data/com.yangfuhai.asimplecachedemo/cache/ACache_4137=org.afinal.simplecache.ACache@2bc38270}
			//{/data/data/com.yangfuhai.asimplecachedemo/cache/ACache_12189=org.afinal.simplecache.ACache@2bc3d890}
			mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager);
		}
		return manager;
	}

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

 

二,存入數據

put(String key, String value)方法寫數據到文件

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

文件放入程序緩存後,統計緩存總量,總數,文件存放到文件map中(value值為文件最後修改時間,便於根據設置的銷毀時間進行銷毀)
緩存沒有超過限制,則增加緩存總量,總數的數值
緩存超過限制,則減少緩存總量,總數的數值
通過removeNext方法找到最老文件的大小

public void put(String key, String value) {
		File file = mCache.newFile(key);
		BufferedWriter out = null;
		try {
			out = new BufferedWriter(new FileWriter(file), 1024);
			out.write(value);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				try {
					out.flush();
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			mCache.put(file);
		}
	}
  //文件放入程序緩存後,統計緩存總量,總數,文件存放到文件map中(value值為文件最後修改時間,便於根據設置的銷毀時間進行銷毀)
		//緩存沒有超過限制,則增加緩存總量,總數的數值
		//緩存超過限制,則減少緩存總量,總數的數值
		//通過removeNext方法找到最老文件的大小
		private void put(File file) {
			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);
		}

 

/**
		 * 移除舊的文件(冒泡,找到最後修改時間最小的文件)
		 * 
		 * @return
		 */
		private long removeNext() {
			if (lastUsageDates.isEmpty()) {
				return 0;
			}

			Long oldestUsage = null;
			File mostLongUsedFile = null;
			Set> entries = lastUsageDates.entrySet();
			synchronized (lastUsageDates) {
				for (Entry entry : entries) {
					if (mostLongUsedFile == null) {
						mostLongUsedFile = entry.getKey();
						oldestUsage = entry.getValue();
					} else {
						Long lastValueUsage = entry.getValue();
						if (lastValueUsage < oldestUsage) {
							oldestUsage = lastValueUsage;
							mostLongUsedFile = entry.getKey();
						}
					}
				}
			}

			long fileSize = calculateSize(mostLongUsedFile);
			if (mostLongUsedFile.delete()) {
				lastUsageDates.remove(mostLongUsedFile);
			}
			return fileSize;
		}


三,獲取數據

getAsString(String key)方法從緩存文件中讀取數據,其中通過Utils.isDue(readString)方法判斷數據是否過期,是否要刪除

public String getAsString(String key) {
		///data/data/com.yangfuhai.asimplecachedemo/cache/ACache/1727748931
		File file = mCache.get(key);
		if (!file.exists())
			return null;
		boolean removeFile = false;
		BufferedReader in = null;
		try {
			in = new BufferedReader(new FileReader(file));
			String readString = ;
			String currentLine;
			while ((currentLine = in.readLine()) != null) {
				readString += currentLine;
			}
			if (!Utils.isDue(readString)) {
				return Utils.clearDateInfo(readString);
			} else {
				removeFile = true;
				return null;
			}
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (removeFile)
				remove(key);
		}
	}

 

/**
		 * 判斷緩存的String數據是否到期
		 * 
		 * @param str
		 * @return true:到期了 false:還沒有到期
		 */
		private static boolean isDue(String str) {
			return isDue(str.getBytes());
		}

		/**
		 * 判斷緩存的byte數據是否到期(到期:當前時間大於保存時間加上保存後的存留時間)
		 * 
		 * @param data
		 * @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 boolean hasDateInfo(byte[] data) {
			return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14;
		}
        //saveDate文件保存時間毫秒數,deleteAfter文件保存後的保留時間毫秒數
		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;
		}


 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved