查看: 721|回复: 0

[Android] 【参赛】 android 缓存图片等数据

[复制链接]
  • TA的每日心情

    2015-6-25 12:42
  • 签到天数: 6 天

    [LV.2]偶尔看看I

    发表于 2014-6-29 17:06:32 | 显示全部楼层 |阅读模式
    【导言】
    采用LinkedHashMap自带的LRU 算法缓存数据, 可检测对象是否已被虚拟机回收,并且重新计算当前缓存大小,清除缓存中无用的键值对象(即已经被虚拟机回收但未从缓存清除的数据);
    * 默认内存缓存大小为: 4 * 1024 * 1024 可通过通过setMaxCacheSize重新设置缓存大小,可手动清空内存缓存
    * <br>支持内存缓存和磁盘缓存方式, 通过 {@link cc.util.cache.NetByteWrapper} 支持HTTP缓存 (注:详细参考cc.util.http包); 注:使用JDK7
    1. package cc.util.cache;

    2. import java.io.Serializable;
    3. import java.util.Objects;

    4. /**
    5.    封装网络数据, 将数据的Etag、lastModified获取到, 下次请求的时候提取出来到服务器比对
    6. * Help to wrap byte data which obtains from network, It will work with {@link cc.util.cache.NetChacheManager}
    7. * @author wangcccong
    8. * @version 1.1406
    9. * <br> create at: Tues, 10 Jun 2014
    10. */
    11. public class NetByteWrapper implements Serializable {

    12.         private final static long serialVersionUID = 1L;

    13.         /** data from network */
    14.         private byte[] data;
    15.         /** data size */
    16.         int contentLength;
    17.         /** latested modify time */
    18.         private long lastModified;
    19.         /** ETag: look up HTTP Protocol */
    20.         private String ETag;

    21.         public NetByteWrapper(byte[] data, long lastModified, String Etag) {
    22.                 this.data = data;
    23.                 this.lastModified = lastModified;
    24.                 this.ETag = Etag;
    25.         }
    26.        
    27.         public byte[] getData() {
    28.                 return data;
    29.         }
    30.         public void setData(byte[] data) {
    31.                 this.data = data;
    32.         }

    33.         public long getLastModified() {
    34.                 return lastModified;
    35.         }
    36.         public void setLastModified(long lastModified) {
    37.                 this.lastModified = lastModified;
    38.         }

    39.         public String getETag() {
    40.                 return ETag;
    41.         }
    42.        
    43.         public void setETag(String eTag) {
    44.                 this.ETag = eTag;
    45.         }
    46.        
    47.         public int getContentLength() {
    48.                 return Objects.isNull(data) ? 0 : data.length;
    49.         }
    50. }


    51. package cc.util.cache;

    52. import java.lang.ref.ReferenceQueue;
    53. import java.lang.ref.SoftReference;

    54. /**采用软引用方式将数据存放起来
    55. * enclose {@link cc.util.cache.NetByteWrapper} with {@link java.lang.ref.SoftReference}, In order to recycle the memory
    56. * @author wangcccong
    57. * @version 1.1406
    58. * <br> create at: Tues, 10 Jun. 2014
    59. */
    60. public class NetByteSoftReference extends SoftReference<NetByteWrapper> {
    61.        
    62.         private String key = "";
    63.         private long length = 0;

    64.         public NetByteSoftReference(String key, NetByteWrapper arg0) {
    65.                 this(key, arg0, null);
    66.         }

    67.         public NetByteSoftReference(String key, NetByteWrapper arg0,
    68.                         ReferenceQueue<? super NetByteWrapper> arg1) {
    69.                 super(arg0, arg1);
    70.                 // TODO Auto-generated constructor stub
    71.                 this.key = key;
    72.                 this.length = arg0.getContentLength();
    73.         }
    74.        
    75.         public String getKey() {
    76.                 return key;
    77.         }
    78.        
    79.         public long getLength() {
    80.                 return length;
    81.         }

    82. }


    83. package cc.util.cache;

    84. import java.lang.ref.ReferenceQueue;
    85. import java.lang.ref.SoftReference;
    86. import java.io.FileInputStream;
    87. import java.io.FileOutputStream;
    88. import java.io.ObjectInputStream;
    89. import java.io.ObjectOutputStream;
    90. import java.util.Iterator;
    91. import java.util.LinkedHashMap;
    92. import java.util.Objects;

    93. /**
    94. * 采用LinkedHashMap自带的LRU 算法缓存数据, 可检测对象是否已被虚拟机回收,并且重新计算当前缓存大小,清除缓存中无用的键值对象(即已经被虚拟机回收但未从缓存清除的数据);
    95. * 默认内存缓存大小为: 4 * 1024 * 1024 可通过通过setMaxCacheSize重新设置缓存大小,可手动清空内存缓存
    96. * <br>支持内存缓存和磁盘缓存方式, 通过 {@link cc.util.cache.NetByteWrapper} 支持HTTP缓存 (注:详细参考cc.util.http包)
    97. * @author wangcccong
    98. * @version 1.1406
    99. * <br> create at: Tues, 10 Jun 2014
    100. */
    101. public class NetCacheManager {

    102.         /** max cache size */
    103.         private long MAX_CACHE_SIZE = 4 * 1024 * 1024;
    104.         private long cacheSize = 0;

    105.         private static NetCacheManager instance = null;
    106.        
    107.         private final ReferenceQueue<NetByteWrapper> referenceQueue;
    108.         private final LinkedHashMap<String, NetByteSoftReference> cacheMap;
    109.        
    110.         private NetCacheManager(){
    111.                 referenceQueue = new ReferenceQueue<NetByteWrapper>();
    112.                 cacheMap = new LinkedHashMap<String, NetByteSoftReference>(16, 0.75f, true) {

    113.                         private static final long serialVersionUID = -8378285623387632829L;
    114.                         @Override
    115.                         protected boolean removeEldestEntry(
    116.                                         java.util.Map.Entry<String, NetByteSoftReference> eldest) {
    117.                                 // TODO Auto-generated method stub
    118.                                 boolean shouldRemove = cacheSize > MAX_CACHE_SIZE;
    119.                                 if (shouldRemove) {
    120.                                         cacheSize -= eldest.getValue().getLength();
    121.                                         System.gc();
    122.                                 }
    123.                                 return shouldRemove;
    124.                         }
    125.                 };
    126.         }
    127.        
    128.         /** singleton model */
    129.         public static synchronized NetCacheManager newInstance(){
    130.                 if (Objects.isNull(instance)) {
    131.                         instance = new NetCacheManager();
    132.                 }
    133.                 return instance;
    134.         }
    135.        
    136.         /**
    137.          * reset the memory cache size
    138.          * @param cacheSize
    139.          */
    140.         public void setMaxCacheSize(long cacheSize) {
    141.                 this.MAX_CACHE_SIZE = cacheSize;
    142.         }
    143.        
    144.         /**
    145.          * 获取当前内存缓存大小
    146.          * @return
    147.          */
    148.         public long getCacheSize() {
    149.                 return cacheSize;
    150.         }
    151.        
    152.         /**
    153.          * 将数据缓存至内存, 如果http返回的数据<b>不支持</b>缓存则采用此方法,缓存的key一般为请求的url
    154.          * @param key
    155.          * @param value
    156.          */
    157.         public void cacheInMemory(String key, byte[] value) {
    158.                 this.cacheInMemory(key, value, 0, null);
    159.         }
    160.        
    161.         /**
    162.          * 将数据缓存至内存, 如果http返回的数据<b>支持</b>缓存则采用此方法
    163.          * @param key
    164.          * @param value
    165.          * @param lastModified
    166.          */
    167.         public void cacheInMemory(String key, byte[] value, long lastModified) {
    168.                 this.cacheInMemory(key, value, lastModified, null);
    169.         }
    170.        
    171.         /**
    172.          * 将数据缓存至内存, 如果http返回的数据<b>支持</b>缓存则采用此方法
    173.          * @param key
    174.          * @param value
    175.          * @param Etags
    176.          */
    177.         public void cacheInMemory(String key, byte[] value, String Etags) {
    178.                 this.cacheInMemory(key, value, 0, Etags);
    179.         }
    180.        
    181.         /**
    182.          * 将数据缓存至内存, 如果http返回的数据<b>支持</b>缓存则采用此方法
    183.          * @param key
    184.          * @param value
    185.          * @param lastModified
    186.          * @param Etags
    187.          */
    188.         private void cacheInMemory(String key, byte[] value, long lastModified, String Etags) {
    189.                 Objects.requireNonNull(key, "key must not be null");
    190.                 clearRecycledObject();
    191.                 NetByteWrapper wrapper = new NetByteWrapper(value, lastModified, Etags);
    192.                 NetByteSoftReference byteRef = new NetByteSoftReference(key, wrapper, referenceQueue);
    193.                 cacheMap.put(key, byteRef);
    194.                 value = null;
    195.                 wrapper = null;
    196.         }
    197.        
    198.         /**
    199.          * 缓存至磁盘, 默认不首先缓存到内存
    200.          * @param key
    201.          * @param value
    202.          * @param path
    203.          */
    204.         public void cacheInDisk(String key, byte[] value, String path) {
    205.                 cacheInDisk(key, value, path, false);
    206.         }
    207.        
    208.         /**
    209.          *
    210.          * @param key
    211.          * @param value
    212.          * @param path
    213.          * @param cacheInMemory
    214.          */
    215.         public void cacheInDisk(String key, byte[] value, String path, boolean cacheInMemory) {
    216.                 this.cacheInDisk(key, value, 0, null, path, cacheInMemory);
    217.         }
    218.        
    219.         /**
    220.          *
    221.          * @param key
    222.          * @param value
    223.          * @param lastModified
    224.          * @param Etags
    225.          * @param path
    226.          * @param cacheInMemory
    227.          */
    228.         private void cacheInDisk(String key, byte[] value, long lastModified, String Etags, String path, boolean cacheInMemory) {
    229.                 if (cacheInMemory) cacheInMemory(key, value, lastModified, Etags);
    230.                 try (FileOutputStream fos = new FileOutputStream(path);
    231.                                 ObjectOutputStream oos = new ObjectOutputStream(fos)) {
    232.                                 NetByteWrapper wrapper = new NetByteWrapper(value, lastModified, Etags);
    233.                                 oos.writeObject(wrapper);
    234.                 } catch (Exception e) {
    235.                                 // TODO: handle exception
    236.                         e.printStackTrace();
    237.                 }
    238.         }
    239.        
    240.         /**
    241.          * get {@link cc.util.cache.NetByteWrapper} from memory according to key
    242.          * @param key
    243.          * @return {@link cc.util.cache.NetByteWrapper}
    244.          */
    245.         public NetByteWrapper getFromMemory(String key) {
    246.                 SoftReference<NetByteWrapper> softReference = cacheMap.get(key);
    247.                 return Objects.nonNull(softReference) ? softReference.get() : null;
    248.         }
    249.        
    250.         /**
    251.          * get byte[] from memory according to key
    252.          * @param context
    253.          * @param key
    254.          * @return
    255.          */
    256.         public byte[] getByteFromMemory(String key) {
    257.                 NetByteWrapper wrapper = getFromMemory(key);
    258.                 return Objects.nonNull(wrapper) ? wrapper.getData() : null;
    259.         }
    260.        
    261.         /**
    262.          * 从磁盘获取数据
    263.          * @param path
    264.          * @return {@link cc.util.cache.NetByteWrapper}
    265.          */
    266.         public NetByteWrapper getFromDisk(String path) {
    267.                 try (FileInputStream fis = new FileInputStream(path);
    268.                                 ObjectInputStream ois = new ObjectInputStream(fis)) {
    269.                         NetByteWrapper wrapper = (NetByteWrapper) ois.readObject();
    270.                         return wrapper;
    271.                 } catch (Exception e) {
    272.                         // TODO: handle exception
    273.                         e.printStackTrace();
    274.                         return null;
    275.                 }
    276.         }
    277.        
    278.         /**
    279.          *
    280.          * @param path
    281.          * @return
    282.          */
    283.         public byte[] getByteFromDisk(String path) {
    284.                 NetByteWrapper wrapper = getFromDisk(path);
    285.                 return Objects.isNull(wrapper) ? null : wrapper.getData();
    286.         }
    287.        
    288.         /**
    289.          * calculate the size of the cache memory
    290.          */
    291.         private void clearRecycledObject() {
    292.                 NetByteSoftReference ref = null;
    293.         //检测对象是否被回收,如果被回收则从缓存中移除死项
    294.                 while (Objects.nonNull((ref = (NetByteSoftReference) referenceQueue.poll()))) {
    295.                         cacheMap.remove(ref.getKey());
    296.                 }
    297.                 cacheSize = 0;
    298.                 Iterator<String> keys = cacheMap.keySet().iterator();
    299.                 while (keys.hasNext()) {
    300.                         cacheSize += cacheMap.get(keys.next()).getLength();
    301.                 }
    302.         }
    303.        
    304.         /**
    305.          * clear the memory cache
    306.          */
    307.         public void clearCache() {
    308.                 clearRecycledObject();
    309.                 cacheMap.clear();
    310.                 System.gc();
    311.                 System.runFinalization();
    312.         }
    313.        
    314. }
    复制代码
    您需要登录后才可以回帖 登录 | 注册青鸟豆号

    本版积分规则

    Copyright 1999-2019 Beijing Aptech Beida Jade Bird Information Technology Co.,Ltd

    北大青鸟IT教育 北京阿博泰克北大青鸟信息技术有限公司 版权所有

    京ICP备11045574号-3 京公网安备11010802013845号

    快速回复 返回顶部 返回列表