在使用ListView,GridView控件时,由于其内部的重用机制,导致item中的内容会被清空,但是如果是网络中下载的内容特别是图片则会比较麻烦,因为经常需要从后台重新加载。为了提高用户体验,需要对图片等数据进行缓存,避免耗时的网络操作。

一、LruCache:android官方提供的用于在内存中进行缓存的一个类。

1     public LruCache(int maxSize) {
2         if (maxSize <= 0) {
3             throw new IllegalArgumentException("maxSize <= 0");
4         }
5         this.maxSize = maxSize;
6         this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
7     }
LruCache构造函数

由构造函数可知,

  1、该缓存系统是使用LinkedHashMap来保存数据的。

  2、需要传入一个int型的数值表示可以存储的最大容量,但是由于存入的数据的类型没有限制,所以添加和删除数据时的size变化就不确定。例如缓存String就可以以个数计算;但是如果存入的是Bitmap,则以其的内存大小计算更合适。!!!所以,在使用该类时通常需要重写其sizeOf(),指定其size变化的规则

该缓存类实现的效果是:先保存然后进行调整,如果超过容量则将最近最早未被使用的数据删除。

 1     public final V put(K key, V value) {
 2         if (key == null || value == null) {
 3             throw new NullPointerException("key == null || value == null");
 4         }
 5 
 6         V previous;
 7         //该同步块中执行put操作,并对size进行调整,一种是覆盖原有key,一种是新建
 8         synchronized (this) {
 9             putCount++;
10             size += safeSizeOf(key, value);
11             previous = map.put(key, value);
12             if (previous != null) {
13                 size -= safeSizeOf(key, previous);
14             }
15         }
16 
17         if (previous != null) {
18             entryRemoved(false, key, previous, value);
19         }
20 
21         //该方法是对总容量的调整:如果超过则删除离header最近的元素,直到小于总容量
22         trimToSize(maxSize);
23         return previous;
24     }
25 
26     public void trimToSize(int maxSize) {
27         while (true) {
28             K key;
29             V value;
30             synchronized (this) {
31                 if (size < 0 || (map.isEmpty() && size != 0)) {
32                     throw new IllegalStateException(getClass().getName()
33                             + ".sizeOf() is reporting inconsistent results!");
34                 }
35 
36                 if (size <= maxSize) {
37                     break;
38                 }
39 
40                 //获取最早保存的数据进行删除
41                 Map.Entry<K, V> toEvict = map.eldest();
42                 if (toEvict == null) {
43                     break;
44                 }
45 
46                 key = toEvict.getKey();
47                 value = toEvict.getValue();
48                 map.remove(key);
49                 size -= safeSizeOf(key, value);
50                 evictionCount++;
51             }
52 
53             entryRemoved(true, key, value, null);
54         }
55     }
LruCache的put()

 二、DiskLruCache:官方认证的硬盘缓存方式,不是android的API,需要下载才能使用。

  1、首先是创建过程,该类不能直接创建,需要通过open方法进行创建,

 1    /* @param directory         缓存路径,
 2    * @param valueCount       每个缓存实体对应的缓存数量,通常是1
 3    * @param maxSize           最大缓存容量
 4    */
 5 
 6 //一个用户获取可用的缓存路径的方法,首先是外部存储器,然后是内部存储器
 7 public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
 8 
 9 public File getDiskCacheDir(Context context, String uniqueName) {
10     String cachePath;
11     if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
12             || !Environment.isExternalStorageRemovable()) {
13         cachePath = context.getExternalCacheDir().getPath();
14     } else {
15         cachePath = context.getCacheDir().getPath();
16     }
17     return new File(cachePath + File.separator + uniqueName);
18 }
19 
20 //获取应用版本号的方法
21     public int getAppVersion(Context context) {
22         try {
23             PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
24             return info.versionCode;
25         } catch (NameNotFoundException e) {
26             e.printStackTrace();
27         }
28         return 1;
29     }

  2、写入缓存:通过DiskLruCache.Editor来操作的,创建该类使用的是edit(),

1 //参数key将作为该缓存的名字,为将请求url和其对应,通常使用md5对其操作生成唯一字符串
2   public Editor edit(String key) throws IOException {
3     return edit(key, ANY_SEQUENCE_NUMBER);
4   }

    创建一个Editor之后就可以通过它生成一个输出流,向缓存文件中进行输出操作。

  3、读取缓存:通过DiskLruCache的get()可以获取一个Snapshot对象,该对象中包含着这个缓存文件的输出流,可以对流进行读取获取其中的缓存。

  4、其他操作:

    ①移除缓存:remove()

    ②获取缓存大小:size()

    ③通过缓存操作到日志文件(也就是journal文件),通常在Activity的onPause()中调用一次即可。

    ④清空缓存:delete()

    ⑤关闭缓存:close(),和open()对应。

 

posted on 2016-05-30 21:33  a发愣的树熊  阅读(130)  评论(0编辑  收藏  举报