**(一):寫在前面的話**?
接著上一篇繼續更新,上一篇文章已經把FastDev4Android項目列表下拉刷新組件(PullToRefreshListView)組件做了講解和使用。今天項目更新是得數據緩存器(ACache)的詳解和使用。?
**(二):功能介紹**?
2.1:基本介紹?
ACache項目是我去年在Github上面發現的一個開源項目,首先感謝作者,感謝Github開源的力量。ACache是一個比較輕量級的數據緩存管理器(一個類ACache.java)解決問題,所以學習起來就非常簡單,在中小型項目中可以較好的去使用。ACache使用采用手機包名路徑下文件數據保存方式進行數據緩存,同時可以自定義設置數據緩存的路徑,緩存的文件大小,以及緩存的文件數量以及相應的緩存過期時間。下面我們來看一下整個類中相應的方法和變量以及常量,這樣對整個類有一個直觀的了解。?
?
?
查看以上各種方法,我們可以知道ACache給我們提供了文本數據,JSON格式數據,圖片等信息緩存,當然我們也可以通過實際的項目情況,對該類進行其他格式數據的擴展。?
2.2:ACache流程?
ACache請求處理流程?
?
**(三):核心方法介紹**?
3.1:相關配置數據設置
~~~
public static final int TIME_HOUR = 60 * 60; //緩存一個小時
public static final int TIME_MINUTE = 60; //混存一分鐘
public static final int TIME_DAY = TIME_HOUR * 12; //緩存一個白天 12個小時
private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb
private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放數據的數量
~~~
以上可以自定義設置緩存時間,緩存文件大小和限制存放數據的數量等信息?
3.2:靜態獲取ACache對象實現方法
~~~
public static ACache get(Context ctx)
public static ACache get(Context ctx, String cacheName)
public static ACache get(File cacheDir)
public static ACache get(Context ctx, long max_zise, int max_count)
~~~
使用者可以根據不同的參數分別獲取ACache管理對象。?
3.3:ACache對象創建方法:?
①:對象獲取
~~~
public static ACache get(File cacheDir, long max_zise, int max_count) {
ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid());
if (manager == null) {
manager = new ACache(cacheDir, max_zise, max_count);
mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager);
}
return manager;
}
~~~
根據以上代碼可以知道在創建ACache對象的時候,會先通過Map Cache緩存中去查找是否已經存在該對象,有直接返回,如果不存在那么進行創建對象實例(通過new ACache(xxx,xx,xx)),然后保存一份到Map緩存中。?
②:對象創建
~~~
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);
}
~~~
以上代碼可以得知最終我們使用的管理器就是ACacheManager實例,在這邊進行緩存器的初始化(文件路徑,緩存數量,緩存大小)以及數據最終保存和獲取。那么最后我們來看一下整個ACacheManger的實現代碼吧:
~~~
public class ACacheManager {
private final AtomicLong cacheSize;
private final AtomicInteger cacheCount;
private final long sizeLimit;
private final int countLimit;
private final Map<File, Long> lastUsageDates = Collections
.synchronizedMap(new HashMap<File, Long>());
protected File cacheDir;
private ACacheManager(File cacheDir, 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 = 0;
int count = 0;
File[] 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(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);
}
private File get(String key) {
File file = newFile(key);
Long currentTime = System.currentTimeMillis();
file.setLastModified(currentTime);
lastUsageDates.put(file, currentTime);
return file;
}
private File newFile(String key) {
return new File(cacheDir, key.hashCode() + "");
}
private boolean remove(String key) {
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();
}
}
}
/**
* 移除舊的文件
*
* @return
*/
private long removeNext() {
if (lastUsageDates.isEmpty()) {
return 0;
}
Long oldestUsage = null;
File mostLongUsedFile = null;
Set<Map.Entry<File, Long>> entries = lastUsageDates.entrySet();
synchronized (lastUsageDates) {
for (Map.Entry<File, Long> 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;
}
private long calculateSize(File file) {
return file.length();
}
}
~~~
**(四):使用介紹**?
我們在使用該工具的時候,很簡單,獲取對象實例,做put和get操作即可?
ACache mACache=ACache.get(Contenxt) 默認獲取方式,或者可以采用另外幾個靜態獲取方法也可以,下面我們來看一下具體實現。
~~~
private Button save_cache;
private Button query_cache;
private EditText edit_cache;
private TextView tv_cache;
private ACache mAcache;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sp_cache_layout);
save_cache=(Button)this.findViewById(R.id.save_cache);
query_cache=(Button)this.findViewById(R.id.query_cache);
edit_cache=(EditText)this.findViewById(R.id.edit_cache);
tv_cache=(TextView)this.findViewById(R.id.tv_cache);
mAcache=ACache.get(this);
//進行保存數據
save_cache.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String save_str = edit_cache.getText().toString().trim();
mAcache.put(CacheConsts.DEMO_CACHE_KEY, save_str);
showToastMsgShort("緩存成功...");
}
});
//進行查詢數據
query_cache.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String query_str=mAcache.getAsString(CacheConsts.DEMO_CACHE_KEY);
tv_cache.setText(query_str);
}
});
}
~~~
運行結果如下:?
?
到此為止我們今天ACache的講解和使用結果,詳細代碼項目地址:?
[https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android)?
同時歡迎大家star和fork整個開源快速開發框架項目~如果有什么意見和反饋,歡迎留言,必定第一時間回復。也歡迎有同樣興趣的童鞋加入到該項目中來,一起維護該項目。
- 前言
- Android快速開發框架介紹(一)
- Android首頁圖片自動無限循環輪播Gallery+FlowIndicator(二)
- Android 列表下拉刷新組件PullToRefreshListView使用(三)
- Android 數據緩存器ACache的詳解和使用(四)
- Android崩潰異常捕捉CustomCrash,提升用戶體驗(五)
- Android實現沉浸式狀態欄(六)
- AndroidAnnnotations注入框架介紹和Android Studios基本配置(七)
- AndroidAnnnotations注入框架的工作原理(八)
- AndroidAnnnotations注入框架使用之注入組件Components(九)
- AndroidAnnnotations注入框架使用之Injection標簽詳解(十)
- AndroidAnnnotations注入框架使用之事件綁定Event Binding(十一)
- AndroidAnnnotations注入框架使用之線程處理Threading(十二)
- AndroidAnnnotations注入框架使用之第三方框架集成RoboGuice(十三)
- AndroidAnnnotations注入框架使用之第三方框架集成Otto事件總線(十四)
- AndroidAnnnotations注入框架使用之第三方框架集成OrmLite(十五)
- AndroidAnnnotations注入框架使用之最佳實踐之Adapters和lists(十六)
- AndroidAnnnotations注入框架使用之最佳實踐SharedPreferences(十七)
- Android MVP開發模式詳解(十九)
- 消息總線EventBus的基本使用(二十)
- 消息總線EventBus源碼分析以及與Otto框架對比(二十一)
- 列表頭生成帶文本或者字母的圖片開源庫TextDrawable使用和詳解(二十二)
- 重寫WebView網頁加載以及JavaScript注入詳解(二十三)
- BaseAdapterHelper的基本使用介紹,讓你擺脫狂寫一堆Adapter煩惱(二十四)
- BaseAdapterHelper詳解源碼分析,讓你擺脫狂寫一堆Adapter煩惱(二十五)
- Volley完全解析之基礎使用(二十六)
- Volley完全解析之進階最佳實踐與二次封裝(二十七)
- RecyclerView完全解析,讓你從此愛上它(二十八)
- RecyclerView完全解析之打造新版類Gallery效果(二十九)
- RecyclerView完全解析之結合AA(Android Annotations)注入框架實例(三十)
- RecyclerView完全解析之下拉刷新與上拉加載SwipeRefreshLayout(三十一)
- CardView完全解析與RecyclerView結合使用(三十二)
- 神器ViewDragHelper完全解析,媽媽再也不擔心我自定義ViewGroup滑動View操作啦~(三十三)
- 神器ViewDragHelper完全解析之詳解實現QQ5.X側滑酷炫效果(三十四)
- 實例解析之SwipeRefreshLayout+RecyclerView+CardView(三十五)
- HorizontalScrollView,Fragment,FragmentStatePagerAdapter打造網易新聞Tab及滑動頁面效果(三十六)
- Android Design支持庫TabLayout打造仿網易新聞Tab標簽效果(三十七)
- 打造QQ6.X最新版本側滑界面效果(三十八)