前言Glide,该功能非常强大 Android  图片加载开源框架 相信大家并不陌生

正由于他的功能强大,所以它的源码非常复杂,这导致很多人望而却步

本人尝试将 Glide 的功能进行分解,并单独针对每个功能进行源码分析,从而降低Glide源码的复杂度。接下来,我将推出一系列关于 Glide的功能源码分析,有兴趣可以继续关注

今天,我将主要讲解在使用Glide缓存功能时的问题:为什么Glide 的缓存无起作用,希望你们会喜欢。

1. 背景Glide实现内存 & 磁盘缓存是根据 图片的缓存Key进行唯一标识

开发者为了降低成本 & 安全,往往会将图片存放在云服务器上如 七牛云 等等。

为了保护 客户的图片资源,图片云服务器 会在图片Url地址的基础上再加一个token参数http://url.com/image.jpg?token=a6cvva6b02c670b0aGlide加载该图片时,会使用加了token参数的图片Url地址 作为

id参数,从而生成 缓存Key

2. 问题作为身份认证的token参数可能会发生变化,并不是一成不变

若 token参数变了,则图片Url跟着变,则生成缓存key的所需id参数发生变化,即 缓存Key也会跟着变化

这导致同一张图片,但因为token参数变化,而导致缓存Key发生变化,从而使得 Glide的缓存功能失效缓存Key发生变化,即同一个图片的当前缓存key 和 之前写入缓存的key不相同,这意味着 在读取缓存时 无法根据当前缓存key 找到之前的缓存,从而使得失效

3. 解决方案

3.1 原理

在 生成缓存Key 的id参数 前,将 带有token参数的图片Url地址 去掉 token参数,从而根据 初始的图片Url地址 生成缓存Key的id参数实现了一个图片的缓存Key的id参数始终唯一 ,即等于 图片Url地址

3.2 储备知识:生成缓存Key的id参数的逻辑

生成缓存Key的id参数的逻辑为:直接将图片的 URL 地址作为缓存Key的id参数public class Engine implements EngineJobListener,

MemoryCache.ResourceRemovedListener,

EngineResource.ResourceListener {

public  LoadStatus load(Key signature, int width, int height, DataFetcher fetcher,

DataLoadProvider loadProvider, Transformation transformation, ResourceTranscoder transcoder,

Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {

Util.assertMainThread();

long startTime = LogTime.getLogTime();

final String id = fetcher.getId();

// 获得了一个id字符串,即需加载图片的唯一标识

// 如,若图片的来源是网络,那么该id = 这张图片的url地址

// fetcher = HttpUrlFetcher的实例,即调用HttpUrlFetcher.getid()->>分析19

EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),transcoder, loadProvider.getSourceEncoder());

// 将该id 和 signature、width、height等10个参数一起传入到缓存Key的工厂方法里,最终创建出一个EngineKey对象

// 创建原理:通过重写equals() 和 hashCode(),保证只有传入EngineKey的所有参数都相同情况下才认为是同一个EngineKey对象

// 该EngineKey 即Glide中的缓存Key

...

}

public class HttpUrlFetcher implements DataFetcher {

...

private final GlideUrl glideUrl;

// GlideUrl = 在上篇文章讲解 图片加载 第2步load()中传入图片url地址时,Glide在内部把图片url地址包装成一个GlideUrl对象

@Override

public String getId() {

return glideUrl.getCacheKey();

// ->>分析20

}

public class GlideUrl {

private final URL url;

private final String stringUrl;

...

// GlideUrl构造函数

public GlideUrl(URL url) {

this(url, Headers.DEFAULT);

}

public GlideUrl(String url) {

this(url, Headers.DEFAULT);

}

public String getCacheKey() {

return stringUrl != null ? stringUrl : url.toString();

// 在生成GlideUrl对象时:

// 若传入的是URL字符串(即图片地址),就直接返回该字符串(大多数是这种情况)

// 若传入的是URL对象,那么就返回这个对象toString()后的结果。

}

...

}

3.3 实现方案

即 我们只需重写getCacheKey() & 将 带有token参数的图片Url地址 去掉 token参数 即可。/**

* 代码实现:创建一个GlideUrl类的子类 & 重写getCacheKey()

**/

// 1. 继承GlideUrl

public class mGlideUrl extends GlideUrl {

private String mUrl;

// 构造函数里 传入 带有token参数的图片Url地址

public MyGlideUrl(String url) {

super(url);

mUrl = url;

}

// 2. 重写getCacheKey()

@Override

public String getCacheKey() {

return mUrl.replace(deleteToken(), "");

// 通过 deleteToken() 从 带有token参数的图片Url地址中 去掉 token参数

// 最终返回一个没有token参数、初始的图片URL地址

// ->>分析1

}

// 分析1:deleteToken()

private String deleteToken() {

String tokenParam = "";

int tokenKeyIndex = mUrl.indexOf("?token=") >= 0 ? mUrl.indexOf("?token=") : mUrl.indexOf("&token=");

if (tokenKeyIndex != -1) {

int nextAndIndex = mUrl.indexOf("&", tokenKeyIndex + 1);

if (nextAndIndex != -1) {

tokenParam = mUrl.substring(tokenKeyIndex + 1, nextAndIndex + 1);

} else {

tokenParam = mUrl.substring(tokenKeyIndex);

}

}

return tokenParam;

}

}

/**

* 使用缓存时:需要在load()中传入自定义的 mGlideUrl对象

**/

Glide.with(this)

.load(new mGlideUrl(url))

.into(imageView);

// 注:a. 若像之前直接传入图片的url地址,那么在内部还是会使用原始的GlideUrl类

//    b. 即直接将传入传入图片的url地址作为缓存key的Id参数,而没有对token参数作任何处理

4. 总结本文主要对Glide的图片缓存功能的使用问题进行讲解

android glide的历史,Android 图片加载的那些事:为什么你的Glide 缓存没有起作用?...相关推荐

  1. Carson带你学Android:主流开源图片加载库对比(UIL、Picasso、Glide、Fresco)

    前言 图片加载在 Android开发项目中十分常见 为了降低开发周期 & 难度,我们经常会选用一些图片加载的开源库,而现在图片加载开源库越来越多,我们应该选用哪种呢? 今天.我就给大家介绍 & ...

  2. Android之Google推荐的图片加载库Glide介绍

    原文链接:Google推荐的图片加载库Glide介绍 作者 : nuuneoi 译者 : jianghejie 校对者 :

  3. android图片传输三方框架,Android开发三种第三方图片加载的框架

    最近在项目中用到了大量图片加载,第三方优秀框架还不错,下面介绍三款榜首的框架用法和问题,做一个记录. 现在项目使用的是Android Studio开发的,现在也没有多少人使用Eclipse了吧. 一. ...

  4. android教你打造独一无二的图片加载框架

    前言 首先,最近是在忙okhttp没错.不过或许有人问为什么忙着okhttp怎么又扯到了图片加载上了.其实,最近想实现下断点续传以及多文件下载,但并不知道怎么搞.群里有小伙伴提出了控制线程池来实现.然 ...

  5. android学习之路(六)---- 图片加载库的优化、封装

    封装Image-Loader 一.背景         universal-image-loader是一项伟大的开源项目,作者在其中运用到的软件工程解决办法让人印象深刻,在本篇文章的开篇,首先向uni ...

  6. Android的屏幕适配之图片加载适配

    Android屏幕适配 一.屏幕尺寸 屏幕尺寸是指手机屏幕的对角线的长度 二.屏幕分辨率 是指在横纵向上的像素点数,单位是Px,1px = 1个像素点,一般以纵向像素*横向像素来表示 三.屏幕像素密度 ...

  7. Android 多张2K,4k图片加载压缩的详解

    前言 在Android开发中,会有2k,4k的多张图片加载的功能,怎么样能保证不会OOM呢,只能对图片进行压缩处理,具体功能如下: //获取资源文件的图片public Bitmap decodeSam ...

  8. 坑:Android从相册中选择图片加载到ImageView中显示不出

  9. Android图片加载框架——Glide(Glide v4)

    原文地址 Android图片加载框架--Glide(Glide v4) 前言 android中图片加载框架有很多,所有框架最终达到的目都是在Android平台上以极度简单的方式加载和展示图片,如果我们 ...

最新文章

  1. MySQL中exists与in的使用
  2. 为什么Java的main方法必须是public static void?
  3. 【Flutter】Flutter 开源项目参考
  4. 【资源汇总分享】Android开发资源汇总之一
  5. pandas删除某列有空值的行_Python-零基础学习Pandas知识点整理(2)
  6. [css] 分析比较opacity: 0、visibility: hidden、display: none三者的优劣和适用场景
  7. Redis持久化RDB
  8. oracle PROFILE的使用学习
  9. Selenium自动化测试-文件上传
  10. python怎么把代码做成软件_python代码能做成软件吗
  11. python图像加密_图像加密注释的Python实现,笔记,python
  12. win7背景颜色设置为淡绿色
  13. 整理了一下以前写的东西,单条记载 现在看看还蛮有意思
  14. 误删通话记录?这几个方法能恢复
  15. 移动高德地图marker点
  16. 阿里云视频点播相关代码
  17. Chapter 30 Web Technology and DBMSs
  18. PTA 7-43 币值转换 (20 分)
  19. 灾害应急管理信息化建设“四步走”——以水旱灾害为例
  20. java学习书籍推荐

热门文章

  1. CIFAR-10数据集可视化Python版本
  2. 操作系统:第四章 文件管理2 - 磁盘管理,磁盘调度算法
  3. vb 如何给静态变量赋初值
  4. 网络协议之:socket协议详解之Datagram Socket
  5. c++分治法求最大最小值实现_快速实现分组统计,均数标准差 中位数(四分位数间距) 最大值 最小值,非常全...
  6. 【附全部代码+图片】使用HTML5+CSS3绘制HTML5的logo——Web前端系列学习笔记
  7. 【详解】CSS阴影用法——Web前端系列学习笔记
  8. centos 7 局域网丢包排查_宽带发生故障怎么办?教你几招轻松排查
  9. Invalid config event received: {version=0, server
  10. linux升级补丁tar,Linux下Bash严重漏洞补丁升级方法