android缓存工具类

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import android.graphics.Bitmap;
 
/**
 * <p>Bitmap缓存池</p>
 *
 * <p>基于2Q改进算法缓存</p>
 * <p>http://www.vldb.org/conf/1994/P439.PDF</p>
 *
 * 使用:
 *    LCache static lCache = new LCache();
 *   
 *    ...
 *   
 *   
 *    String imgUrl = "http://monstar.ch/uploads/img/201212/22085340_Zun9.jpg";
 *    if(lCache.isCached(imgUrl)){
 *        Bitmap tBitmap = lCache.get(imgUrl);
 *    }else{
 *        //从服务端获取图像
 *        Bitmap tBitmap = 服务端获取的Bitmap
 *        
 *        lCache.put(imgUrl,tBitmap);
 *    }
 *
 * @author lei.guoting
 */
public class LCache{
        private static final int DEFAULT_MAX_SIZE = (int)(1024 * 1024 * 3.5f);      //默认缓存池大小  3.5M
        private static final int DEFAULT_IN_QUEUE_MAX_SIZE = 40;                    //fInCacheQue队列默认大小
        private static final int DEFAULT_OUT_QUEUE_MAX_SIZE = 60;                   //fOutCacheQue队列默认大小
        private static final int DEFAULT_CACHE_QUEUE_MAX_SIZE = 0;                  //finalCacheQue队列默认大小
         
        private final HashMap<String,Ref> cache;           //缓存池
    private final Queue<String> fInCacheQue;           //一级缓存,Ain
    private final Queue<String> fOutCacheQue;          //清楚一级缓存记录,Aout
    private final Queue<String> finalCacheQue;         //最终缓存,Am
     
    private final int cacheMaxSize;
    private int size;
    private int curBitmapSize;
         
        /**
         * 构建默认大小的Cache
         */
        public LCache() {
                this(DEFAULT_MAX_SIZE);
        }
         
        /**
         * 构建指定大小的Cache
         *
         * @param cacheMaxSize Cache最大容量
         */
        public LCache(int cacheMaxSize){
                if(0 >= cacheMaxSize){
                        throw new IllegalArgumentException("cacheMaxSize must be greater than 0");
                }
                 
                this.cacheMaxSize = cacheMaxSize;
                this.cache = new HashMap<String,Ref>();
                this.fInCacheQue = new Queue<String>(DEFAULT_IN_QUEUE_MAX_SIZE);
                this.fOutCacheQue = new Queue<String>(DEFAULT_OUT_QUEUE_MAX_SIZE);
                this.finalCacheQue = new Queue<String>(DEFAULT_CACHE_QUEUE_MAX_SIZE);
        }
         
        /**
         *
         * @param key key值
         * <a href="\"http://www.eoeandroid.com/home.php?mod=space&uid=7300\"" target="\"_blank\"">@return</a>  true-key对应的Bitmap在该缓存池中
         *          false-key对应的Bitmap不在该缓存池中
         */
        public synchronized boolean isCached(String key){
                return this.cache.containsKey(key);
        }
         
        /**
         * 获取缓存池中Bitmap
         *
         * @param key key值
         * @return   Bitmap
         */
        public Bitmap get(String key){
                if(null == key){
                        throw new NullPointerException("The key can not be null");
                }
                 
                if("".equals(key)){
                        throw new IllegalArgumentException("The key dons't value");
                }
                 
                return this.getFromCache(key);
        }
         
        /**
         * 将Bitmap缓存到该缓存池中
         *
         * @param key
         * @param mBitmap
         */
    public synchronized void put(String key,Bitmap mBitmap){
            if(this.cache.containsKey(key)){
                    return ;
            }
             
        if(this.fOutCacheQue.contains(key)){
                this.finalCacheQue.addToHead(key);
                this.fOutCacheQue.remove(key);
                this.reclaimCache(key,mBitmap);
        }
         
        else{
                this.fInCacheQue.addToHead(key);
                this.reclaimCache(key,mBitmap);
                if(this.fInCacheQue.isOverflow()){
                        String tKey = this.fInCacheQue.removeFromTail();
                        this.clearCache(tKey);
                        this.fOutCacheQue.addToHead(tKey);
                        this.fOutCacheQue.trim();
                }
        }
    }
     
    private void reclaimCache(String key, Bitmap mBitmap){
            if(this.hasFreeCache(mBitmap)){
            this.putIntoCache(key, mBitmap);
            }
             
            else if(this.fInCacheQue.isOverflow()){
                    do{
                            String tKey = this.fInCacheQue.removeFromTail();
                            this.clearCache(tKey);
                            this.fOutCacheQue.addToHead(key);
                    }while(this.cacheMaxSize < (this.size + this.curBitmapSize));                   
                    this.fOutCacheQue.trim();
                    this.putIntoCache(key, mBitmap);                   
            }
             
            else{
                    do{
                            String tKey = this.finalCacheQue.removeFromTail();
                            this.clearCache(tKey);
                    }while(this.cacheMaxSize < (this.size + this.curBitmapSize));                    
                    this.putIntoCache(key, mBitmap);
            }
    }
     
    private void putIntoCache(String key, Bitmap mBitmap){
            this.cache.put(key, new Ref(mBitmap,this.curBitmapSize));
                this.size += this.curBitmapSize;
                this.curBitmapSize = 0;
    }
     
    private boolean hasFreeCache(Bitmap mBitmap){
            boolean hasFreeCache = true;
            this.curBitmapSize = this.sizeOf(mBitmap);
            if(this.cacheMaxSize < (this.size + this.curBitmapSize)){
                    hasFreeCache = false;
            }
             
            return hasFreeCache;
    }
     
    private void clearCache(String key){
            Ref  tRef = this.cache.remove(key);
        if(null != tRef){
                this.size -= tRef.getSize();
                if(null != tRef.getBitmap()){
                    tRef.getBitmap().recycle();       
                }
        }
    }
     
    private Bitmap getFromCache(String key){
            Bitmap tBitmap = null;
            synchronized(this){
                    if(this.finalCacheQue.contains(key)){
                        this.finalCacheQue.moveToHead(key);
                }
                    tBitmap = this.cache.get(key).getBitmap();
            }
             
            return  tBitmap;
    }
         
        /**
         * Bitmap 存储大小
         *
         * @param mBitmap
         * @return
         */
        private int sizeOf (Bitmap mBitmap){
                int weight = 0;
                switch(mBitmap.getConfig()){
                case ALPHA_8 :
                        weight = 1;
                        break;
                case ARGB_4444 :
                        weight = 2;
                        break;
                case ARGB_8888 :
                        weight = 4;
                        break;
                case RGB_565 :
                        weight = 2;
                        break;
                default :
                        weight = 1;
                        break;
                }
 
                return (mBitmap.getWidth() * mBitmap.getHeight() * weight);
        }
         
        public synchronized void destory(){
                this.cache.clear();
                this.finalCacheQue.clear();
                this.fInCacheQue.clear();
                this.fOutCacheQue.clear();
        }
         
         
        /**
         * 队列
         */
        class Queue<T>{
            private int capacity;
                 
            private final List<T> list;
             
            /**
             * @param capacity  队列最大容量,可为0;如果capacity为0,当前队列无大小限制
             */
                public Queue(int capacity){
                        this.capacity = capacity;
                        if(0 < this.capacity){
                                this.list = new ArrayList<T>(this.capacity);
                        }else{
                                this.list = new LinkedList<T>();
                        }
                         
                }
                 
                /**
                 * 队列容量
                 *
                 * @return 队列容量
                 */
                public int capacity(){
                        return this.capacity;
                }
                 
                /**
                 * 队列当前大小
                 *
                 * @return 队列大小
                 */
                public int size(){
                        return this.list.size();
                }
                 
                /**
                 * 该队列中是否有key值
                 *
                 * @param key
                 * @return true 存在key值,false 不存在key值
                 */
                public boolean contains(T key){
                        return this.list.contains(key);
                }
                 
                /**
                 * 队列是否溢出
                 *
                 * @return
                 */
                public boolean isOverflow(){
                        if(0 == capacity){
                                return false;
                        }
                         
                        else{
                                return (this.list.size() > this.capacity);       
                        }
                }
                 
                /**
                 * 将队列中key移动到队列头
                 *
                 * @param key 值
                 */
                public void moveToHead(T key){
                        this.list.remove(key);
                        this.list.add(key);
                }
                 
                /**
                 * 将key添加到队列头
                 *
                 * @param key 值
                 */
                public void addToHead(T key){
                        this.list.add(key);
                }
                 
                /**
                 * 删除队列最后一个值
                 *
                 * @return 当前删除队列值
                 */
                public T removeFromTail(){
                        T tKey = null;
                        if(0 < this.list.size()){
                                tKey = this.list.remove(0);
                        }
                        return tKey;
                }
                 
                /**
                 * 删除队列中key值
                 *
                 * @param key  key值
                 * @return   删除成功返回当前key,删除失败返回null
                 */
                public T remove(T key){
                        if(this.list.remove(key)){
                                return key;
                        }
                        return null;
                }
                 
                /**
                 * 将Queue中超过capacity的长度截取掉
                 *      如果list.size <= capacity, 什么都不做
                 */
                public void trim(){
                        if((0 == capacity) || (this.list.size() <= this.capacity)){
                                return ;
                        }
                         
                        int tNum = this.list.size() - this.capacity;
                        for(int idx = 0; idx < tNum; idx ++){
                                this.removeFromTail();
                        }
                }
                 
                public void clear(){
                        this.list.clear();
                }
        }
         
        class Ref{
                //private SoftReference<Bitmap> softReference;
                private Bitmap mBitmap;
                private int size;
                 
                public Ref(Bitmap mBitmap,int size){
                        //this.softReference = new SoftReference<Bitmap>(mBitmap);
                        this.mBitmap = mBitmap;
                        this.size = size;
                }
                 
                public int getSize(){
                        return size;
                }
                 
                public Bitmap getBitmap(){
                        //return softReference.get();
                        return this.mBitmap;
                }
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值