android实现缓存图片等数据
程序员文章站
2022-07-11 18:39:45
采用linkedhashmap自带的lru 算法缓存数据, 可检测对象是否已被虚拟机回收,并且重新计算当前缓存大小,清除缓存中无用的键值对象(即已经被虚拟机回收但未从缓存清...
采用linkedhashmap自带的lru 算法缓存数据, 可检测对象是否已被虚拟机回收,并且重新计算当前缓存大小,清除缓存中无用的键值对象(即已经被虚拟机回收但未从缓存清除的数据);
* 默认内存缓存大小为: 4 * 1024 * 1024 可通过通过setmaxcachesize重新设置缓存大小,可手动清空内存缓存
* <br>支持内存缓存和磁盘缓存方式, 通过 cc.util.cache.netbytewrapper} 支持http缓存 (注:详细参考cc.util.http包); 注:使用jdk7
package cc.util.cache; import java.io.serializable; import java.util.objects; /** 封装网络数据, 将数据的etag、lastmodified获取到, 下次请求的时候提取出来到服务器比对 * help to wrap byte data which obtains from network, it will work with {@link cc.util.cache.netchachemanager} * @author wangcccong * @version 1.1406 * <br> create at: tues, 10 jun 2014 */ public class netbytewrapper implements serializable { private final static long serialversionuid = 1l; /** data from network */ private byte[] data; /** data size */ int contentlength; /** latested modify time */ private long lastmodified; /** etag: look up http protocol */ private string etag; public netbytewrapper(byte[] data, long lastmodified, string etag) { this.data = data; this.lastmodified = lastmodified; this.etag = etag; } public byte[] getdata() { return data; } public void setdata(byte[] data) { this.data = data; } public long getlastmodified() { return lastmodified; } public void setlastmodified(long lastmodified) { this.lastmodified = lastmodified; } public string getetag() { return etag; } public void setetag(string etag) { this.etag = etag; } public int getcontentlength() { return objects.isnull(data) ? 0 : data.length; } } package cc.util.cache; import java.lang.ref.referencequeue; import java.lang.ref.softreference; /**采用软引用方式将数据存放起来 * enclose {@link cc.util.cache.netbytewrapper} with {@link java.lang.ref.softreference}, in order to recycle the memory * @author wangcccong * @version 1.1406 * <br> create at: tues, 10 jun. 2014 */ public class netbytesoftreference extends softreference<netbytewrapper> { private string key = ""; private long length = 0; public netbytesoftreference(string key, netbytewrapper arg0) { this(key, arg0, null); } public netbytesoftreference(string key, netbytewrapper arg0, referencequeue<? super netbytewrapper> arg1) { super(arg0, arg1); // todo auto-generated constructor stub this.key = key; this.length = arg0.getcontentlength(); } public string getkey() { return key; } public long getlength() { return length; } } package cc.util.cache; import java.lang.ref.referencequeue; import java.lang.ref.softreference; import java.io.fileinputstream; import java.io.fileoutputstream; import java.io.objectinputstream; import java.io.objectoutputstream; import java.util.iterator; import java.util.linkedhashmap; import java.util.objects; /** * 采用linkedhashmap自带的lru 算法缓存数据, 可检测对象是否已被虚拟机回收,并且重新计算当前缓存大小,清除缓存中无用的键值对象(即已经被虚拟机回收但未从缓存清除的数据); * 默认内存缓存大小为: 4 * 1024 * 1024 可通过通过setmaxcachesize重新设置缓存大小,可手动清空内存缓存,支持采用内存映射方式读取缓存 * <br>支持内存缓存和磁盘缓存方式, 通过 {@link cc.util.cache.netbytewrapper} 支持http缓存 (注:详细参考cc.util.http包) * @author wangcccong * @version 1.1406 * <br> create at: tues, 10 jun 2014 */ public class netcachemanager { /** max cache size */ private long max_cache_size = 4 * 1024 * 1024; private long cachesize = 0; private static netcachemanager instance = null; private final referencequeue<netbytewrapper> referencequeue; private final linkedhashmap<string, netbytesoftreference> cachemap; private netcachemanager(){ referencequeue = new referencequeue<netbytewrapper>(); cachemap = new linkedhashmap<string, netbytesoftreference>(16, 0.75f, true) { private static final long serialversionuid = -8378285623387632829l; @override protected boolean removeeldestentry( java.util.map.entry<string, netbytesoftreference> eldest) { // todo auto-generated method stub boolean shouldremove = cachesize > max_cache_size; if (shouldremove) { cachesize -= eldest.getvalue().getlength(); system.gc(); } return shouldremove; } }; } /** singleton model */ public static synchronized netcachemanager newinstance(){ if (objects.isnull(instance)) { instance = new netcachemanager(); } return instance; } /** * reset the memory cache size * @param cachesize */ public void setmaxcachesize(long cachesize) { this.max_cache_size = cachesize; } /** * 获取当前内存缓存大小 * @return */ public long getcachesize() { return cachesize; } /** * 将数据缓存至内存, 如果http返回的数据<b>不支持</b>缓存则采用此方法,缓存的key一般为请求的url * @param key * @param value */ public void cacheinmemory(string key, byte[] value) { this.cacheinmemory(key, value, 0, null); } /** * 将数据缓存至内存, 如果http返回的数据<b>支持</b>缓存则采用此方法 * @param key * @param value * @param lastmodified */ public void cacheinmemory(string key, byte[] value, long lastmodified) { this.cacheinmemory(key, value, lastmodified, null); } /** * 将数据缓存至内存, 如果http返回的数据<b>支持</b>缓存则采用此方法 * @param key * @param value * @param etags */ public void cacheinmemory(string key, byte[] value, string etags) { this.cacheinmemory(key, value, 0, etags); } /** * 将数据缓存至内存, 如果http返回的数据<b>支持</b>缓存则采用此方法 * @param key * @param value * @param lastmodified * @param etags */ private void cacheinmemory(string key, byte[] value, long lastmodified, string etags) { objects.requirenonnull(key, "key must not be null"); clearrecycledobject(); netbytewrapper wrapper = new netbytewrapper(value, lastmodified, etags); netbytesoftreference byteref = new netbytesoftreference(key, wrapper, referencequeue); cachemap.put(key, byteref); value = null; wrapper = null; } /** * 缓存至磁盘, 默认不首先缓存到内存 * @param key * @param value * @param path */ public void cacheindisk(string key, byte[] value, string path) { cacheindisk(key, value, path, false); } /** * * @param key * @param value * @param path * @param cacheinmemory */ public void cacheindisk(string key, byte[] value, string path, boolean cacheinmemory) { this.cacheindisk(key, value, 0, null, path, cacheinmemory); } /** * * @param key * @param value * @param lastmodified * @param etags * @param path * @param cacheinmemory */ private void cacheindisk(string key, byte[] value, long lastmodified, string etags, string path, boolean cacheinmemory) { if (cacheinmemory) cacheinmemory(key, value, lastmodified, etags); try (fileoutputstream fos = new fileoutputstream(path); objectoutputstream oos = new objectoutputstream(fos)) { netbytewrapper wrapper = new netbytewrapper(value, lastmodified, etags); oos.writeobject(wrapper); } catch (exception e) { // todo: handle exception e.printstacktrace(); } } /** * get {@link cc.util.cache.netbytewrapper} from memory according to key * @param key * @return {@link cc.util.cache.netbytewrapper} */ public netbytewrapper getfrommemory(string key) { softreference<netbytewrapper> softreference = cachemap.get(key); return objects.nonnull(softreference) ? softreference.get() : null; } /** * get byte[] from memory according to key * @param context * @param key * @return */ public byte[] getbytefrommemory(string key) { netbytewrapper wrapper = getfrommemory(key); return objects.nonnull(wrapper) ? wrapper.getdata() : null; } /** * 从磁盘获取数据 * @param path * @return {@link cc.util.cache.netbytewrapper} */ public netbytewrapper getfromdisk(string path) { try (fileinputstream fis = new fileinputstream(path); objectinputstream ois = new objectinputstream(fis)) { netbytewrapper wrapper = (netbytewrapper) ois.readobject(); return wrapper; } catch (exception e) { // todo: handle exception e.printstacktrace(); return null; } } /** * 采用内存映射的方式从磁盘获取数据(加快读取缓存的大文件) * @param path * @return */ public netbytewrapper getfromdiskbymapped(string path) { try (fileinputstream fis = new fileinputstream(path); filechannel channel= fis.getchannel(); bytearrayoutputstream baos = new bytearrayoutputstream()){ mappedbytebuffer mbb = channel.map(filechannel.mapmode.read_only, 0, channel.size()); byte[] bts = new byte[1024]; int len = (int) channel.size(); for (int offset = 0; offset < len; offset += 1024) { if (len - offset > 1024) mbb.get(bts); else mbb.get((bts = new byte[len - offset])); baos.write(bts); } bytearrayinputstream bais = new bytearrayinputstream(baos.tobytearray()); objectinputstream ois = new objectinputstream(bais); netbytewrapper wrapper = (netbytewrapper) ois.readobject(); bais.close(); ois.close(); return wrapper; } catch (exception e) { // todo: handle exception e.printstacktrace(); return null; } } /** * 从磁盘获取缓存的byte[] 数据 * @param path * @return */ public byte[] getbytefromdisk(string path) { netbytewrapper wrapper = getfromdisk(path); return objects.isnull(wrapper) ? null : wrapper.getdata(); } /** * 通过内存映射放射从磁盘获取缓存的byte[] 数据 * @param path * @return */ public byte[] getbytefromdiskbymapped(string path) { netbytewrapper wrapper = getfromdiskbymapped(path); return objects.isnull(wrapper) ? null : wrapper.getdata(); } /** * calculate the size of the cache memory */ private void clearrecycledobject() { netbytesoftreference ref = null; //检测对象是否被回收,如果被回收则从缓存中移除死项 while (objects.nonnull((ref = (netbytesoftreference) referencequeue.poll()))) { cachemap.remove(ref.getkey()); } cachesize = 0; iterator<string> keys = cachemap.keyset().iterator(); while (keys.hasnext()) { cachesize += cachemap.get(keys.next()).getlength(); } } /** * clear the memory cache */ public void clearcache() { clearrecycledobject(); cachemap.clear(); system.gc(); system.runfinalization(); } }
以上所述就是本文的全部内容了,希望大家能够喜欢。
上一篇: Android微信支付开发问题
下一篇: 素炒茶树菇,这样做才好吃
推荐阅读