欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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();
  }
   
}

以上所述就是本文的全部内容了,希望大家能够喜欢。