- MemoryCache内存缓存类讲解
- 使用SoftReference做的内存缓存类
- 文件缓存类FileCache讲解
MemoryCache内存缓存类讲解
内存缓存即把数据保存在内存中,如果缓存的数据超过设定的内存限制就删除最先缓存进来的数据。下面的MemoryCache缓存类是先创建一个Map对象(这里缓存的是Bitmap数据,所以Map的值为Bitmap),把缓存数据存入这个map对象中,想缓存数据时调用put(String id,Bitmap bitmap)方法,想从内存缓存中取数据时调用 get(String id)。
get(String id)方法的原理是先通过判断cache对象中是否包含要得到的键,如果包含就返回该键对应的值,如果不包含返回null。
put(String id,Bitmap bitmap)方法判断是否包含该键,如果包含,缓存中图片所占用的字节的值需要将该键对应的bitmap对象所占用的内存减掉,再将该bitmap加入到cache对象中,检查现在的缓存的内存值即调用checkSize方法。checkSize方法中计算内存是否超过设定的值,如果超过了,就从cache对象中移除最先缓存的对象
内存缓存类MemoryCache代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
public
class
MemoryCache {
private
static
final
String TAG =
"MemoryCache"
;
/**放入缓存时是个同步操作
*LinkedHashMap构造方法的最后一个参数true代表这个map里的元素将按照最
*近使用次数由少到多排列,即LRU。
*这样的好处是如果要将缓存中的元素替换,则先遍历出最近最少使用的元素来替换以提高效率*/
private
Map
.synchronizedMap(
new
LinkedHashMap
10
,
1
.5f,
true
));
// 缓存中图片所占用的字节,初始0,将通过此变量严格控制缓存所占用的堆内存
private
long
size =
0
;
// current allocated size
// 缓存只能占用的最大堆内存
private
long
limit =
1000000
;
// max memory in bytes
public
MemoryCache() {
// use 25% of available heap size
setLimit(Runtime.getRuntime().maxMemory() /
4
);
}
public
void
setLimit(
long
new_limit) {
limit = new_limit;
Log.i(TAG,
"MemoryCache will use up to "
+ limit /
1024
. /
1024
. +
"MB"
);
}
public
Bitmap get(String id) {
try
{
if
(!cache.containsKey(id))
return
null
;
return
cache.get(id);
}
catch
(NullPointerException ex) {
return
null
;
}
}
public
void
put(String id, Bitmap bitmap) {
try
{
if
(cache.containsKey(id))
size -= getSizeInBytes(cache.get(id));
cache.put(id, bitmap);
size += getSizeInBytes(bitmap);
checkSize();
}
catch
(Throwable th) {
th.printStackTrace();
}
}
/**
* 严格控制堆内存,如果超过将首先替换最近最少使用的那个图片缓存
*
*/
private
void
checkSize() {
Log.i(TAG,
"cache size="
+ size +
" length="
+ cache.size());
if
(size > limit) {
// 先遍历最近最少使用的元素
Iterator
while
(iter.hasNext()) {
Entry
size -= getSizeInBytes(entry.getValue());
iter.remove();
if
(size <= limit)
break
;
}
Log.i(TAG,
"Clean cache. New size "
+ cache.size());
}
}
public
void
clear() {
cache.clear();
}
/**
* 图片占用的内存
*
* @param bitmap
* @return
*/
long
getSizeInBytes(Bitmap bitmap) {
if
(bitmap ==
null
)
return
0
;
return
bitmap.getRowBytes() * bitmap.getHeight();
}
}
|
使用SoftReference做的内存缓存类
也可以使用SoftReference,代码会简单很多,不过我们推荐使用上面的一种方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public
class
MemoryCache {
private
Map
.synchronizedMap(
new
HashMap
public
Bitmap get(String id) {
if
(!cache.containsKey(id))
return
null
;
SoftReference
return
ref.get();
}
public
void
put(String id, Bitmap bitmap) {
cache.put(id,
new
SoftReference
}
public
void
clear() {
cache.clear();
}
}
|
文件缓存类FileCache讲解
文件缓存类的作用也就是把文件保存到SD卡上,下面是文件缓存类的代码FileCache.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
public
class
FileCache {
private
File cacheDir;
public
FileCache(Context context) {
// 如果有SD卡则在SD卡中建一个LazyList的目录存放缓存的图片
// 没有SD卡就放在系统的缓存目录中
if
(android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED))
cacheDir =
new
File(
android.os.Environment.getExternalStorageDirectory(),
"LazyList"
);
else
cacheDir = context.getCacheDir();
if
(!cacheDir.exists())
cacheDir.mkdirs();
}
public
File getFile(String url) {
// 将url的hashCode作为缓存的文件名
String filename = String.valueOf(url.hashCode());
// Another possible solution
// String filename = URLEncoder.encode(url);
File f =
new
File(cacheDir, filename);
return
f;
}
public
void
clear() {
File[] files = cacheDir.listFiles();
if
(files ==
null
)
return
;
for
(File f : files)
f.delete();
}
}
|