图片加载框架之内存缓存(一级缓存)设计(3)---- LruMemoryCache

【概要】

数据结构存储 - LinkedHashMap;默认先进先出规则。

缓存大小采用app内存的1/8,单位MB

这里的话,基本没什么难度,都是一些日常操作,直接上代码。


【LruMemoryCache】

public class LruMemoryCache implements MemoryCache{

    private final LinkedHashMap<String, Bitmap> map;// 默认 - (先进先出)

    private final int maxSize;//单位 - bytes; 最大容量限制

    private int curSize;//单位 - bytes; 当前缓存大小

    /** @param maxSize Maximum sum of the sizes of the Bitmaps in this cache */
    public LruMemoryCache(int maxSize) {
        if (maxSize <= 0) {
            throw new IllegalArgumentException("maxSize <= 0");
        }

        this.maxSize = maxSize;
        this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);// 加载因子 - http://my.oschina.net/weiweiblog/blog/612812
    }

    /***
     * 放到队列的头
     * */
    @Override
    public final boolean put(String key, Bitmap value) {
        if (key == null || value == null) {
            throw new NullPointerException("key == null || value == null");
        }

        synchronized (this) {
            curSize += sizeOf(value);
            Bitmap previous = map.put(key, value);//先put,如果一个bitmap大到离谱才oom吧,毕竟app内存的1/8才用来缓存
            if (previous != null) {
                curSize -= sizeOf(previous);
            }
        }

        //
        trimToSize(maxSize);
        return true;
    }

    /**
     * Returns the Bitmap for {@code key} if it exists in the cache. If a Bitmap was returned, it is moved to the head
     * of the queue. This returns null if a Bitmap is not cached.
     */
    @Override
    public final Bitmap get(String key) {
        if (key == null) {
            throw new NullPointerException("key == null");
        }

        synchronized (this) {
            return map.get(key);
        }
    }

    @Override
    public Bitmap remove(String key) {
        if (key == null) {
            throw new NullPointerException("key == null");
        }

        synchronized (this) {
            Bitmap previous = map.remove(key);
            if (previous != null) {
                curSize -= sizeOf(previous);
            }
            return previous;
        }
    }

    @Override
    public Collection<String> keys() {
        synchronized (this) {
            return new HashSet<String>(map.keySet());
        }
    }

    @Override
    public void clear() {
        trimToSize(-1); // -1 will evict 0-sized elements
    }

    /**
     * @desc 计算一个 Bitmap 的大小
     * @return 单位为bytes的大小
     */
    private int sizeOf(Bitmap value) {
        return value.getRowBytes() * value.getHeight();
    }

    /**
     * Remove the eldest entries until the total of remaining entries is at or below the requested curSize.
     *
     * @param maxSize the maximum curSize of the cache before returning. May be -1 to evict even 0-sized elements.
     */
    private void trimToSize(int maxSize) {
        while (true) {
            String key;
            Bitmap value;
            synchronized (this) {
                if (curSize < 0 || (map.isEmpty() && curSize != 0)) {
                    throw new IllegalStateException(getClass().getName() + ".sizeOf() is reporting inconsistent results!");
                }

                if (curSize <= maxSize || map.isEmpty()) {
                    break;
                }

                Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next();
                // [entrySet 学习url] - http://blog.csdn.net/huxin1/article/details/6171023
                if (toEvict == null) {
                    break;
                }
                key = toEvict.getKey();
                value = toEvict.getValue();
                map.remove(key);
                curSize -= sizeOf(value);
            }
        }
    }

    @Override
    public synchronized final String toString() {
        return String.format("LruCache[maxSize = %d bytes]", maxSize);
    }
}


【配置工厂 - ConfigurationFactory】

public class ConfigurationFactory {

    private static final int CONFIG_MEMORY_DIV = 8;
    private static final int MB = 1024 * 1024;

    /**
     * Creates default implementation of {@link MemoryCache} - {@link LruMemoryCache}<br />
     */
    public static MemoryCache createMemoryCache(Context context, int memoryCacheSize) {
        if(memoryCacheSize < 0 )memoryCacheSize = 0;

        if (memoryCacheSize == 0) {
            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            int memoryClass = am.getMemoryClass();//MB
            if (hasHoneycomb() && isLargeHeap(context)) {
                memoryClass = getLargeMemoryClass(am);
            }
            memoryCacheSize = MB * memoryClass / CONFIG_MEMORY_DIV;//默认app内存的1/8
        }
        return new LruMemoryCache(memoryCacheSize);
    }

    private static boolean hasHoneycomb() {// Android 3.1
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
    }

    /*
    * application的标记位,是否需要高耗内存
    * 学习链接 - http://blog.csdn.net/zhangli_/article/details/51735395
    * */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private static boolean isLargeHeap(Context context) {
        // flag & MB
        return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_LARGE_HEAP) != 0;
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private static int getLargeMemoryClass(ActivityManager am) {
        return am.getLargeMemoryClass();
    }

}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值