IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 浅析Glide三级缓存 -> 正文阅读

[移动开发]Android 浅析Glide三级缓存

Android 简要分析Glide三级缓存

概括

Glide version is 4.8.0

Glide拥有三级缓存,分别为

  1. 当前正在使用得资源缓存(ActiveResources)
  2. 内存缓存(LruCache)
  3. 磁盘缓存(DiskLruCache)

LRU(Lest Resently Used)算法,在内存缓存和磁盘缓存中均有用得到,笔者写过一篇Kotlin版本的LruCache的实现,感兴趣的可以查看。Kotlin LruCache

缓存读取

缓存大致分为两大部分,内存缓存与磁盘缓存,而内存缓存又包含正在激活使用的弱引用缓存与LruCache。故为三级缓存。

内存

内存缓存默认开启,如需关闭则进行如下调用。

Glide.with(this)
     .load(url)
	  //关闭内存缓存
     .skipMemoryCache(true)
     .into(iv)

在图片加载过程中,会进去到Engine#load方法中,下面放上部分源代码:

  public <R> LoadStatus load(...){
  ...
    //获取缓存图片的key
    EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
        resourceClass, transcodeClass, options);
	//从弱引用缓存中获取,若获取成功则返回并调用onResourceReady进行成功回调
    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    if (active != null) {
      cb.onResourceReady(active, DataSource.MEMORY_CACHE);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from active resources", startTime, key);
      }
      return null;
    }
	//从内存缓存LruCache中获取,若成功获取则返回并调用onResourceReady进行成功回调
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
      cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from cache", startTime, key);
      }
      return null;
    }
    //若上方的缓存没用命中,则构建EngineJob,随后会进行磁盘缓存获取、网络请求
  ...
  }

上方总的流程是首先从弱引用缓存中取,再去从内存中去取。

首先分析一下弱引用缓存

  private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {
    if (!isMemoryCacheable) {
      return null;
    }
    //从ActiveResources中获取资源
    EngineResource<?> active = activeResources.get(key);
    if (active != null) {
      //当前资源被引用了 +1
      active.acquire();
    }

    return active;
  }
  final class ActiveResources {
    //HashMap 中 储存了弱引用资源
  	final Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();
  }

内存缓存LruCache

private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
  if (!isMemoryCacheable) {
    return null;
  }
  //内部调用remove方法,返回当前资源并且将其从内存LruCache中移除
  EngineResource<?> cached = getEngineResourceFromCache(key);
  if (cached != null) {
    //资源被引用+1
    cached.acquire();
    //将当前资源加入到 弱引用集合
    activeResources.activate(key, cached);
  }
  return cached;
}

上方的注释很明确了,但是我们发现,内存的二级缓存中存在着交互,比如说,如果从内存LruCache中找到资源后,内存中就将该资源移除了,转而加入到弱引用集合中了。

那么上面还有一个资源引用数+1是干什么的呢?

它主要统计当前资源被多少个地方引用/使用(一张图片被多个地方展示),其中被引用一次就+1,这时候资源肯定都在弱引用集合,如果不引用资源了就-1,直到引用数为0,就将资源从弱引用集合存入到内存LruCache。

总的来说,弱引用集合存的是当前正在使用的资源(若不使用,随时被系统回收),重复利用;内存LruCache,存的则是,之前使用过但当前不再使用过的资源。二者之间存在交互。

而整体内存缓存主要的作为即为防止同一张图片(包括尺寸大小都一样)的资源,被重复加入内存,同时提高相应速度。

磁盘

磁盘缓存有存在以下五种策略:默认为AUTOMATIC

  • ALL 远程图片资源使用 DATA 和 RESOURCE 缓存,本地图片只使用 RESOURCE 缓存;
  • NONE 不缓存任何图片资源;
  • DATA 将检索到的原始图片资源(解码之前的)写入磁盘缓存;
  • RESOURCE 将检索到的原始图片资源解码之后(压缩或转换)再写入磁盘缓存;
  • AUTOMATIC 尝试根据数据源智能选择策略,数据源可以是:DataFetcher、EncodeStrategy、ResourceEncoder;

使用diskCacheStrategy可以调整缓存策略,比如:

Glide.with(this)
     .load(url)
     .diskCacheStrategy(DiskCacheStrategy.ALL)
     .into(iv);

若上方内存二级缓存没用命中,则会执行到接下来的流程DecodeJob#onDataFetcherReady

  @Override
  public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
      DataSource dataSource, Key attemptedKey) {
    ...
      try {
        //会从磁盘获取数据
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }

总结

三级缓存读取顺序为:弱引用缓存 -> LruCache -> DiskLruCache。

创作不易,如有帮助一键三连咯🙆?♀?。欢迎技术探讨噢!

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 12:02:43  更:2022-05-10 12:03:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:36:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码