美文网首页面试题
Glide框架手写实现(四)磁盘缓存

Glide框架手写实现(四)磁盘缓存

作者: 程序员三千_ | 来源:发表于2020-03-23 14:46 被阅读0次

Glide框架手写实现(一)资源封装
Glide框架手写实现(二)活动缓存
Glide框架手写实现(三)内存缓存
Glide框架手写实现(四)磁盘缓存
Glide框架手写实现(五)生命周期

上一篇文章,我们封装了活动缓存和内存缓存,现在我们要先明确一个概念,不管是活动缓存还是内存缓存,只有在app运行的时候,才会生效,如果你把app杀死了,这两个缓存就没用了,所以才引出我们今天的主题“磁盘缓存”
。磁盘缓存是保存在sd卡中的,所以就算你app杀死了,下次启动还是可以去找到里面的图片的。


image.png

解释一下glide框架加载图片到imageview的流程:一个app启动,里面有个imageview要加载图片,首先会去活动缓存中去查找,如果找到了,直接返回给app加载,如果找不到,去内存缓存中找,找到了,会先从内存缓存中加载到活动缓存中,app再从活动缓存中去加载,(活动缓存和内存缓存是互斥的,图片对象在二者中只能存在一个,不明白的去看上一篇文章),如果内存缓存中还是找不到,才会去磁盘缓存中去查找,找到了,也会先从磁盘缓存中加载到活动缓存中,app再从活动缓存中去加载,如果磁盘缓存还是找不到,才会去调用外部资源加载(网络加载或者本地加载)。
这就是图片框架加载的整个流程。

流程先讲到这里,等我们把全部的“砖块”都封装好,去用我们手写的glide框架真正加载图片的时候,我们再具体讲一下流程(后续文章中),现在我们先进入这篇文章的正题,开始封装磁盘缓存。

我们磁盘缓存的封装,是在DiskLruCache的基础上进行的,DiskLruCache大家都知道,是android之神JakeWharton在2011年写的一个框架,在github上可以找到,
https://github.com/JakeWharton/DiskLruCache/tree/master/src/main/java/com/jakewharton/disklrucache
DiskLruCache的回收机制也是Lru最小使用算法,只是他把数据存放在了本地sd中(磁盘),不是存放在内存中而已。我们把它的代码down下来放入自己的工程里,然后真正开始我们的步骤。

/**
 * 我们自己的 磁盘缓存的封装
 * 目的:put  把我们的Value 存储进去
 *      get 通过key 得到 Value
 */
public class DiskLruCacheImpl {

    private final String TAG = DiskLruCacheImpl.class.getSimpleName();

    // Sdcard/disk_lru_cache_dir/ac037ea49e34257dc5577d1796bb137dbaddc0e42a9dff051beee8ea457a4668/缓存东西(Value)
    private final String DISKLRU_CACHE_DIR = "disk_lru_cache_dir"; // 磁盘缓存的的目录

    private final int APP_VERSION = 1; // 我们的版本号,一旦修改这个版本号,之前的缓存失效
    private final int VALUE_COUNT = 1; // 通常情况下都是1
    private final long MAX_SIZE = 1024 * 1024 * 10; // 以后修改成 使用者可以设置的

    private DiskLruCache diskLruCache;

    public DiskLruCacheImpl() {
        // SD 路径
        File file = new File(Environment.getExternalStorageDirectory() + File.separator + DISKLRU_CACHE_DIR);
        try {
            diskLruCache = DiskLruCache.open(file, APP_VERSION, VALUE_COUNT, MAX_SIZE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // TODO put
    public void put(String key, Value value) {
        Tool.checkNotEmpty(key);

        DiskLruCache.Editor editor = null;
        OutputStream outputStream = null;
        try {
            editor = diskLruCache.edit(key);
            outputStream = editor.newOutputStream(0);// index 不能大于 VALUE_COUNT
            Bitmap bitmap = value.getmBitmap();
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); // 把bitmap写入到outputStream
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
            // 失败
            try {
                editor.abort();
            } catch (IOException e1) {
                e1.printStackTrace();
                Log.e(TAG, "put: editor.abort() e:" + e.getMessage());
            }
        } finally {
            try {
                editor.commit(); // sp 记得一定要提交

                diskLruCache.flush();
            } catch (IOException e) {
                e.printStackTrace();
                Log.e(TAG, "put: editor.commit(); e:" + e.getMessage());
            }

            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e(TAG, "put: outputStream.close(); e:" + e.getMessage());
                }
            }
        }
    }

    // TODO get
    public Value get(String key) {
        Tool.checkNotEmpty(key);

        InputStream inputStream = null;
        try {
            DiskLruCache.Snapshot snapshot = diskLruCache.get(key);
            // 判断快照不为null的情况下,在去读取操作
            if (null != snapshot) {
                Value value = Value.getInstance();
                inputStream = snapshot.getInputStream(0);// index 不能大于 VALUE_COUNT
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                value.setmBitmap(bitmap);
                // 保存key 唯一标识
                value.setKey(key);
                return value;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e(TAG, "get: inputStream.close(); e:" + e.getMessage());
                }
            }
        }
        return null; // 为了后续好判断
    }
}

DISKLRU_CACHE_DIR是我们要存放图片的sd卡的目录,APP_VERSION、VALUE_COUNT、MAX_SIZE这三个成员变量,在使用DiskLruCache时会使用到,APP_VERSION代表版本号,这个不要乱改动,一旦你开始使用,然后再去改它的值,之前的缓存会失效的,MAX_SIZE就是你可以最大缓存的大小。在DiskLruCacheImpl的构造函数里,我们new一个file,传入sd卡目录,
然后调用DiskLruCache的open方法。像上两节一样,磁盘缓存也需要添加和移除方法,就是我们上面的put方法和get方法。(put和get方法是DiskLruCache的基本使用,我这里就不讲了,网上很多教程),我们这样讲一下get方法里的这段代码

   Value value = Value.getInstance();
                inputStream = snapshot.getInputStream(0);// index 不能大于 VALUE_COUNT
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                value.setmBitmap(bitmap);
                // 保存key 唯一标识
                value.setKey(key);

这段代码就是拿到DiskLruCache里最终的bitmap,存到我们自己封装的Value对象里。

磁盘缓存我们就封装到这里。大家主要是了解活动缓存,内存缓存,磁盘缓存各自的用处。下一节我们开始实现glide的生命周期的封装。

相关文章

  • Glide框架手写实现(四)磁盘缓存

    Glide框架手写实现(一)资源封装Glide框架手写实现(二)活动缓存Glide框架手写实现(三)内存缓存Gli...

  • Android图片加载框架——Glide

    Glide使用教程 Glide是一个快速有效的开源图像加载框架,可实现内存缓存、磁盘缓存,完成对图片资源的加载,汇...

  • Glide缓存汇总

    Glide缓存汇总 1、Glide有内存缓存和磁盘缓存 2、缓存策略 3、内存缓存 4、磁盘缓存 5、缓存位置和大...

  • Glide实现原理

    一.Glide缓存机制 Glide采取的多级缓存机制,能够较为友好地实现图片、动图的加载。其主要有 内存缓存+磁盘...

  • Glide源码修改-自定义磁盘缓存实现永久存储

    Glide图片磁盘缓存 在《Glide实现WebView离线图片的酷炫展示效果》[https://www.jian...

  • glide缓存无法更新

    问题 使用glide加载图片,glide有缓存,分为内存缓存和磁盘缓存,可以通过diskCacheStrategy...

  • Glide图片加载框架

    1、Glide图片加载框架三级缓存活动缓存、内存缓存、磁盘缓存第一次:首先去查找顺序活动缓存——》内存缓村———》...

  • Glide(图片加载)

    Glide Glide使用文档 Glide 系列教程 玩转Glide的Target对象 Glide-内存缓存与磁盘...

  • Glide 加载相同的URL导致无法更新图片问题

    简介:Glide在加载图片的时候默认使用了缓存机制。Glide的缓存机制分为二级:内存缓存、磁盘缓存。缓存的过程是...

  • LruCache解析

    前言 在学习Glide的时候, 我们会看到Glide的二级缓存, 分别分为内存缓存和磁盘缓存, 而不论哪种缓存都使...

网友评论

    本文标题:Glide框架手写实现(四)磁盘缓存

    本文链接:https://www.haomeiwen.com/subject/drkwyhtx.html