【構建Android快取模組】(二)Memory Cache & File Cache
上節課我們講到普通應用快取Bitmap的實現分析,根據MVC的實現原理,我將這個簡單的快取實現單獨寫成一個模組,這樣可以方便以後的使用,對於任意的需求,都屬於一個可插拔式的功能。
之前提到,這個快取模組主要有兩個子部件:
Memory Cache:記憶體快取的存取速度非常驚人,遠遠快於檔案讀取,如果沒有記憶體限制,當然首選這種方式。遺憾的是我們有著16M的限制(當然大多數裝置限制要高於Android官方說的這個數字),這也正是大Bitmap容易引起OOM的原因。Memory Cache將使用WeakHashMap作為快取的中樞,當程式記憶體告急時,它會主動清理部分弱引用(因此,當引用指向為null,我們必須轉向硬碟快取讀取資料,如果硬碟也沒有,那還是重新下載吧)。
能力越大,責任越大?人家只是跑得快了點兒,總得讓人家休息,我們一定不希望讓記憶體成為第一位跑完馬拉松的Pheidippides,一次以後就掛了吧?作為精打細算的猿媛,我們只能將有限的記憶體分配給Memory
Cache,將更繁重的任務託付給任勞任怨的SDCard。
File Cache:硬碟讀取速度當然不如記憶體,但是為了珍惜寶貴的流量,不讓你的使用者在月底沒有流量時嚎叫著要刪掉你開發的“流量殺手”,最好是避免重複下載。在第一次下載以後,將資料儲存在本地即可。
檔案讀寫的技術並不是很新穎的技術,Java Core那點兒就夠你用了。不過要記得我們可是將Bitmap寫入檔案啊,怎麼寫入呢?不用著急,Android的Bitmap本身就具備將資料寫入OutputStream的能力。我將這些額外的方法寫在一個幫助類中:BitmapHelper
01 |
public static boolean saveBitmap(File
file, Bitmap bitmap){ |
02 |
if (file
== null ||
bitmap == null ) |
03 |
return false ; |
04 |
try { |
05 |
BufferedOutputStream
out = new BufferedOutputStream( new FileOutputStream(file)); |
06 |
return bitmap.compress(CompressFormat.JPEG, 100 ,
out); |
07 |
} catch (FileNotFoundException
e) { |
08 |
e.printStackTrace(); |
09 |
return false ; |
10 |
} |
11 |
} |
01 |
public class MemoryCache
{ |
02 |
private static final String
TAG = "MemoryCache" ; |
03 |
|
04 |
//WeakReference
Map: key=string, value=Bitmap |
05 |
private WeakHashMap<String,
Bitmap> cache = new WeakHashMap<String,
Bitmap>(); |
06 |
|
07 |
/** |
08 |
*
Search the memory cache by a unique key. |
09 |
*
@param key Should be unique. |
10 |
*
@return The Bitmap object in memory cache corresponding to specific key. |
11 |
*
*/ |
12 |
public Bitmap
get(String key){ |
13 |
if (key
!= null ) |
14 |
return cache.get(key); |
15 |
return null ; |
16 |
} |
17 |
|
18 |
/** |
19 |
*
Put a bitmap into cache with a unique key. |
20 |
*
@param key Should be unique. |
21 |
*
@param value A bitmap. |
22 |
*
*/ |
23 |
public void put(String
key, Bitmap value){ |
24 |
if (key
!= null &&
! "" .equals(key)
&& value != null ){ |
25 |
cache.put(key,
value); |
26 |
//Log.i(TAG,
"cache bitmap: " + key); |
27 |
Log.d(TAG, "size
of memory cache: " +
cache.size()); |
28 |
} |
29 |
} |
30 |
31 |
/** |
32 |
*
clear the memory cache. |
33 |
*
*/ |
34 |
public void clear()
{ |
35 |
cache.clear(); |
36 |
} |
37 |
} |
01 |
public class FileCache
{ |
02 |
|
03 |
private static final String
TAG = "MemoryCache" ; |
04 |
|
05 |
private File
cacheDir; //the
directory to save images |
06 |
07 |
/** |
08 |
*
Constructor |
09 |
*
@param context The context related to this cache. |
10 |
*
*/ |
11 |
public FileCache(Context
context) { |
12 |
//
Find the directory to save cached images |
13 |
if (android.os.Environment.getExternalStorageState() |
14 |
.equals(android.os.Environment.MEDIA_MOUNTED)) |
15 |
cacheDir
= new File( |
16 |
android.os.Environment.getExternalStorageDirectory(), |
17 |
Config.CACHE_DIR); |
18 |
else |
19 |
cacheDir
= context.getCacheDir(); |
20 |
if (!cacheDir.exists()) |
21 |
cacheDir.mkdirs(); |
22 |
|
23 |
Log.d(TAG, "cache
dir: " +
cacheDir.getAbsolutePath()); |
24 |
} |
25 |
26 |
/** |
27 |
*
Search the specific image file with a unique key. |
28 |
*
@param key Should be unique. |
29 |
*
@return Returns the image file corresponding to the key. |
30 |
*
*/ |
31 |
public File
getFile(String key) { |
32 |
File
f = new File(cacheDir,
key); |
33 |
if (f.exists()){ |
34 |
Log.i(TAG, "the
file you wanted exists " +
f.getAbsolutePath()); |
35 |
return f; |
36 |
} else { |
37 |
Log.w(TAG, "the
file you wanted does not exists: " +
f.getAbsolutePath()); |
38 |
} |
39 |
40 |
return null ; |
41 |
} |
42 |
43 |
/** |
44 |
*
Put a bitmap into cache with a unique key. |
45 |
*
@param key Should be unique. |
46 |
*
@param value A bitmap. |
47 |
*
*/ |
48 |
public void put(String
key, Bitmap value){ |
49 |
File
f = new File(cacheDir,
key); |
50 |
if (!f.exists()) |
51 |
try { |
52 |
f.createNewFile(); |
53 |
} catch (IOException
e) { |
54 |
e.printStackTrace(); |
55 |
} |
56 |
//Use
the util's function to save the bitmap. |
57 |
if (BitmapHelper.saveBitmap(f,
value)) |
58 |
Log.d(TAG, "Save
file to sdcard successfully!" ); |
59 |
else |
60 |
Log.w(TAG, "Save
file to sdcard failed!" ); |
61 |
|
62 |
} |
63 |
|
64 |
/** |
65 |
*
Clear the cache directory on sdcard. |
66 |
*
*/ |
67 |
public void clear()
{ |
68 |
File[]
files = cacheDir.listFiles(); |
69 |
for (File
f : files) |
70 |
f.delete(); |
71 |
} |
72 |
} |
相關文章
- oracle cache快取Oracle快取
- Guava學習:Cache快取Guava快取
- Spring Cache快取框架Spring快取框架
- Linux Cache MemoryLinux
- Android快取機制-LRU cache原理與用法Android快取
- Spring Cache快取註解Spring快取
- 快取融合(Cache Fusion)介紹快取
- SpringBoot系列——cache快取Spring Boot快取
- 淺聊HTTP快取 (HTTP Cache)HTTP快取
- 全棧必備:快取cache全棧快取
- 全棧必備——快取Cache全棧快取
- Spring Boot Cache Redis快取Spring BootRedis快取
- 快取的Cache Aside模式快取IDE模式
- LRU cache快取簡單實現快取
- localStorage和SessionStorage,Application,Cache快取SessionAPP快取
- Mysql 查詢快取 query_cacheMySql快取
- HTTP請求的快取(Cache)機制HTTP快取
- JAVA 拾遺 — CPU Cache 與快取行Java快取
- 寫Cache快取物件測試例項快取物件
- Linux系統下清空Cache快取Linux快取
- ansible 開啟facts_cache快取快取
- 基於Spring Cache實現二級快取(Caffeine+Redis)Spring快取Redis
- oracle x$bh及v$bh與table cache表快取系列(二)Oracle快取
- [.net 物件導向程式設計進階] (15) 快取(Cache)(二) 利用快取提升程式效能物件程式設計快取
- 【Cache】將常用的“小表”快取到Buffer Cache快取
- 微軟BI 之SSIS 系列 - Lookup 元件的使用與它的幾種快取模式 - Full Cache, Partial Cache, NO Cache...微軟元件快取模式
- oracle result cache 結果集快取的使用Oracle快取
- HTTP快取——304與200 from cacheHTTP快取
- 在Buffer Cache中自動大表快取快取
- 查詢快取(query_cache)的影響快取
- 如何配置極狐GitLab Runner Cache 快取Gitlab快取
- Android okHttp網路請求之快取控制Cache-ControlAndroidHTTP快取
- Spring Boot 揭祕與實戰(二) 資料快取篇 - Redis CacheSpring Boot快取Redis
- Spring Boot 揭祕與實戰(二) 資料快取篇 - Guava CacheSpring Boot快取Guava
- 【Azure Redis 快取 Azure Cache For Redis】Redis連線池Redis快取
- Python 的快取機制: functools.lru_cachePython快取
- Web(Cache)Browser for Mac(Safari快取瀏覽工具)1.7WebMac快取
- 解鎖快取新姿勢——更靈活的 Cache快取