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

【前言】

图片加载框架之内存缓存(一级缓存)设计(1)   中,我们采用HashMap 和 Reference 设计了图片内存缓存日常操作(增,删,查等)。

有了数据的操作之后,我接下来就开始设计大小的限制,因为我们每个app的内存都是有限制的,不可能让我们的缓存无限大。


【缓存大小设置的策略】

curCacheSize - 当前缓存大小(单位bit)

curBitmapSize - 要添加进来的bitmap的大小(单位bit)

sizeLimit - 我们将要限制的缓存的大小(单位bit)

(1)当我们往缓存里面添加一个bitmap的时候,如果curCacheSize + curBitmapSize 大于 sizeLimit,那么就不断删除掉缓存里面保存的bitmap,直到curCacheSize curBitmapSize 小于 sizeLimit,我们才把要添加进来的bitmap加入缓存。但是,这样还是有可能出现oom风险的(当加入的bitmap过大的时候),这个我们后期再看下怎么处理。

(2)在(1)中,我们说到了“不断删除缓存里面保存的bitmap”,这里我们直接用抽象方法替代,因为删除的规则,后面子类可以拓展,方便我们设计删除策略(比如:先进先出,后进先出,LRU等)。


【代码】

import android.graphics.Bitmap;
import com.example.util.L;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * - 固定大小的缓存设计
 * - 抽象方法 removeNext 可以拓展队列的规则(先进先出,后进先出等)
 * - 抽象方法 getSize 根据bitmap,算出bit为单位的大小
 * */
public abstract class LimitedMemoryCache extends BaseMemoryCache{

    private static final int MAX_NORMAL_CACHE_SIZE_IN_MB = 16;//最大缓存,这里默认16 M
    private static final int MAX_NORMAL_CACHE_SIZE = MAX_NORMAL_CACHE_SIZE_IN_MB * 1024 * 1024;

    private final int sizeLimit;//缓存大小 单位bit
    private final AtomicInteger curCacheSize;//  单位ibit

    /**
     * 这里保持有缓存的强引用,缓存对象add规则:加到最后一个
     * 如果超过限制的大小,删除第一个缓存对象
     * 但是超过的可以继续以at {@link #softMap} 存在 ( 父类 BaseMemoryCache里面的 Reference 集合)
     * 数据结构采用链表型的集合 LinkedList,让插入和删除效率更高点
     * 同时采用 synchronizedList 让本来不安全的 LinkedList 变得安全
     */
    private final List<Bitmap> hardCache = Collections.synchronizedList(new LinkedList<Bitmap>());

    /**@param limit Maximum size for cache (in bytes)
     * @desc 设置缓存大小限制,但是不能操作最大限度,否则抛出异常
     * */
    public LimitedMemoryCache(int limit) {
        sizeLimit = limit;
        curCacheSize = new AtomicInteger();

        if (sizeLimit > MAX_NORMAL_CACHE_SIZE) {
            L.w("You set too large memory cache size (more than %1$d Mb)", MAX_NORMAL_CACHE_SIZE_IN_MB);
            throw new RuntimeException("You set too large memory cache");
        }
    }

    @Override
    public boolean put(String key, Bitmap value) {
        boolean putSuccessfully = false;
        // 放进强引用集合里面
        int valueSize = getSize(value);//取决于子类
        int sizeLimit = getSizeLimit();
        int curSize = curCacheSize.get();
        if (valueSize < sizeLimit) {//
            while (curSize + valueSize > sizeLimit) {// 当前大小 + 要put进来的大小 > 缓存大小limit,这时候删除
                Bitmap removedValue = removeNext();//取决于子类(删除策略取决于子类)
                if (hardCache.remove(removedValue)) {//删除强引用
                    curSize = curCacheSize.addAndGet(-getSize(removedValue));//更新当前的缓存大小
                }
            }
            //添加
            hardCache.add(value);
            curCacheSize.addAndGet(valueSize);

            putSuccessfully = true;
        }

        // Add value to soft cache (添加到父类的 Reference 集合)
        super.put(key, value);
        return putSuccessfully;
    }

    @Override
    public Bitmap remove(String key) {
        Bitmap value = super.get(key);//先在 父类 Reference 集合取出
        if (value != null) {
            if (hardCache.remove(value)) {//删除本类的强引用,更新当前缓存大小变量
                curCacheSize.addAndGet(-getSize(value));
            }
        }
        return super.remove(key);
    }

    @Override
    public void clear() {
        hardCache.clear();
        curCacheSize.set(0);
        super.clear();
    }

    protected int getSizeLimit() {
        return sizeLimit;
    }

    protected abstract int getSize(Bitmap value);// 根据图片,得到大小

    protected abstract Bitmap removeNext();//强引用 linklist 的删除规则,子类定义
}


【源码这里下载】

https://github.com/zgxzgxzg/openSource.git



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值