三级缓存

来源:互联网 发布:衣橱软件 编辑:程序博客网 时间:2024/04/28 02:47

三级缓存是:内存缓存,内存缓存,网络缓存。我们加载图片用得就是三级缓存。
他们读取的优先级:
1. 内存缓存 速度快, 优先读取
2. 本地缓存 速度其次, 内存没有,读本地
3. 网络缓存 速度最慢, 本地也没有,才访问网络

  • 内存缓存:内存缓存指的是把图片缓存在内存里,需要再次用到的时候从内存读取。我们通常的做法是建一个集合,然后同过key,value,的形式存储。
    这里我们要用软引用来做,因为不管android设备总内存是多大, 都只给每个app分配一定内存大小,这个内存通常只有十几M,到几十M。
    所以一但缓存处理不当就很容易造成内存溢出。所以我们就要靠垃圾回收器来帮我们回收,从而减少内存溢出的可能。
    平时new一个对象的时候,默认使用的是强引用,垃圾回收器是不会回收的,所以这里我们要使用软引用:
//声明一个软引用的集合    private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new HashMap<String, SoftReference<Bitmap>>();        // 使用软引用将bitmap包装起来,然后存进集合    SoftReference<Bitmap> soft = new SoftReference<Bitmap>(bitmap);         mMemoryCache.put(url, soft);        //读取缓存的数据     SoftReference<Bitmap> softReference = mMemoryCache.get(url);         if (softReference != null) {         Bitmap bitmap = softReference.get();         return bitmap;        }

用软引用把要存储的对象给包装起来,这样垃圾回收器会考虑回收,当然,出了软引用,还有弱引用和虚引用,垃圾回收器会更优先回收
弱引用,最优先回收虚引用。

但是,从 Android 2.3 (API 9)开始 垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。

Google建议使用LruCache。
重源码上可以看到,LruCache 和我们用软引用是差不多的,他只是给集合定了一个大小,当集合缓存的数据大小超过了定义的大小,
那么他就会把将最近最少使用的对象回收掉, 从而保证内存不会超出范围。

// 获取分配给app的内存大小        long maxMemory = Runtime.getRuntime().maxMemory();            //我们通常用app内存大小的8分之1        mMemoryCache = new LruCache<String, Bitmap>((int) (maxMemory / 8)) {            // 返回每个缓存对象的大小            @Override            protected int sizeOf(String key, Bitmap value) {                // int byteCount = value.getByteCount();                int byteCount = value.getRowBytes() * value.getHeight();// 计算图片大小:每行字节数*高度                return byteCount;            }        };

这里是他删除缓存的条件:不停地执行循环,一旦集合大小超过了定义的大小,就把最前面的删除

    public void trimToSize(int maxSize) {        while (true) {            K key;            V value;            synchronized (this) {                if (size < 0 || (map.isEmpty() && size != 0)) {                    throw new IllegalStateException(getClass().getName()                            + ".sizeOf() is reporting inconsistent results!");                }                if (size <= maxSize || map.isEmpty()) {                    break;                }                Map.Entry<K, V> toEvict = map.entrySet().iterator().next();                key = toEvict.getKey();                value = toEvict.getValue();                map.remove(key);                size -= safeSizeOf(key, value);                evictionCount++;            }            entryRemoved(true, key, value, null);        }    }

内存缓存就是这样了。

  • 本地缓存
    把要缓存的文件存到sd卡里,同通常我们是把url同过MD5加密来当文件名来存储,因为有一些url里面包含特殊符号,创建文件会失败,
    当我们要用到缓存的时候会用url加密成MD5看看sd卡里有没有这个文件,如果有就直接读取,再把文件存到内存里,如果没有,就再去从网络获取。

  • 网络缓存
    内存,和本地都没有缓存的时候,通过url去网络上获取到文件,然后再把文件缓存到本地和内存。

0 0
原创粉丝点击