android實(shí)現(xiàn)緩存圖片等數(shù)據(jù)
采用LinkedHashMap自帶的LRU 算法緩存數(shù)據(jù), 可檢測對象是否已被虛擬機(jī)回收,并且重新計(jì)算當(dāng)前緩存大小,清除緩存中無用的鍵值對象(即已經(jīng)被虛擬機(jī)回收但未從緩存清除的數(shù)據(jù));
* 默認(rèn)內(nèi)存緩存大小為: 4 * 1024 * 1024 可通過通過setMaxCacheSize重新設(shè)置緩存大小,可手動清空內(nèi)存緩存
* <br>支持內(nèi)存緩存和磁盤緩存方式, 通過 {@link cc.util.cache.NetByteWrapper} 支持HTTP緩存 (注:詳細(xì)參考cc.util.http包); 注:使用JDK7
package cc.util.cache;
import java.io.Serializable;
import java.util.Objects;
/**
封裝網(wǎng)絡(luò)數(shù)據(jù), 將數(shù)據(jù)的Etag、lastModified獲取到, 下次請求的時(shí)候提取出來到服務(wù)器比對
* 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;
/**采用軟引用方式將數(shù)據(jù)存放起來
* 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 算法緩存數(shù)據(jù), 可檢測對象是否已被虛擬機(jī)回收,并且重新計(jì)算當(dāng)前緩存大小,清除緩存中無用的鍵值對象(即已經(jīng)被虛擬機(jī)回收但未從緩存清除的數(shù)據(jù));
* 默認(rèn)內(nèi)存緩存大小為: 4 * 1024 * 1024 可通過通過setMaxCacheSize重新設(shè)置緩存大小,可手動清空內(nèi)存緩存,支持采用內(nèi)存映射方式讀取緩存
* <br>支持內(nèi)存緩存和磁盤緩存方式, 通過 {@link cc.util.cache.NetByteWrapper} 支持HTTP緩存 (注:詳細(xì)參考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;
}
/**
* 獲取當(dāng)前內(nèi)存緩存大小
* @return
*/
public long getCacheSize() {
return cacheSize;
}
/**
* 將數(shù)據(jù)緩存至內(nèi)存, 如果http返回的數(shù)據(jù)<b>不支持</b>緩存則采用此方法,緩存的key一般為請求的url
* @param key
* @param value
*/
public void cacheInMemory(String key, byte[] value) {
this.cacheInMemory(key, value, 0, null);
}
/**
* 將數(shù)據(jù)緩存至內(nèi)存, 如果http返回的數(shù)據(jù)<b>支持</b>緩存則采用此方法
* @param key
* @param value
* @param lastModified
*/
public void cacheInMemory(String key, byte[] value, long lastModified) {
this.cacheInMemory(key, value, lastModified, null);
}
/**
* 將數(shù)據(jù)緩存至內(nèi)存, 如果http返回的數(shù)據(jù)<b>支持</b>緩存則采用此方法
* @param key
* @param value
* @param Etags
*/
public void cacheInMemory(String key, byte[] value, String Etags) {
this.cacheInMemory(key, value, 0, Etags);
}
/**
* 將數(shù)據(jù)緩存至內(nèi)存, 如果http返回的數(shù)據(jù)<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;
}
/**
* 緩存至磁盤, 默認(rèn)不首先緩存到內(nèi)存
* @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;
}
/**
* 從磁盤獲取數(shù)據(jù)
* @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;
}
}
/**
* 采用內(nèi)存映射的方式從磁盤獲取數(shù)據(jù)(加快讀取緩存的大文件)
* @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[] 數(shù)據(jù)
* @param path
* @return
*/
public byte[] getByteFromDisk(String path) {
NetByteWrapper wrapper = getFromDisk(path);
return Objects.isNull(wrapper) ? null : wrapper.getData();
}
/**
* 通過內(nèi)存映射放射從磁盤獲取緩存的byte[] 數(shù)據(jù)
* @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;
//檢測對象是否被回收,如果被回收則從緩存中移除死項(xiàng)
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();
}
}
以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。
相關(guān)文章
Kotlin高階函數(shù)reduce與fold使用實(shí)例
Kotlin的高階函數(shù)reduce和fold可以用來對集合進(jìn)行聚合操作。reduce函數(shù)將集合元素逐個(gè)累加,而fold函數(shù)則可以指定一個(gè)初始值進(jìn)行累加。這兩個(gè)函數(shù)在處理大數(shù)據(jù)集時(shí)非常有用2023-04-04
Flutter質(zhì)感設(shè)計(jì)之彈出菜單
這篇文章主要為大家詳細(xì)介紹了Flutter質(zhì)感設(shè)計(jì)之彈出菜單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08
Android Studio配置國內(nèi)鏡像源(利用hosts)
這篇文章主要介紹了Android Studio配置國內(nèi)鏡像源(利用hosts),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Kotlin編程基礎(chǔ)數(shù)據(jù)類型示例詳解
這篇文章主要為大家介紹了Kotlin編程基礎(chǔ)數(shù)據(jù)類型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Android利用CountDownTimer實(shí)現(xiàn)驗(yàn)證碼倒計(jì)時(shí)效果實(shí)例
這篇文章主要給大家介紹了關(guān)于Android如何利用CountDownTimer實(shí)現(xiàn)驗(yàn)證碼倒計(jì)時(shí)效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10
Android內(nèi)核源碼 在Ubuntu上下載,編譯,安裝
本文主要介紹Android內(nèi)核源碼,想學(xué)習(xí)深入研究Android的朋友肯定要看看Android內(nèi)核知識的,這里對下載Android內(nèi)核源代碼的下載,安裝,編譯做了詳細(xì)的介紹,有興趣的小伙伴可以參考下2016-08-08

