Android 图片加载的那些事:为什么你的Glide 缓存没有起作用?
2018-02-05 09:29
447 查看
前言
Glide,该功能非常强大
Android图片加载开源框架 相信大家并不陌生
正由于他的功能强大,所以它的源码非常复杂,这导致很多人望而却步
本人尝试将
Glide的功能进行分解,并单独针对每个功能进行源码分析,从而降低
Glide源码的复杂度。
接下来,我将推出一系列关于
Glide的功能源码分析,有兴趣可以继续关注
今天,我将主要讲解在使用
Glide缓存功能时的问题:为什么Glide 的缓存无起作用,希望你们会喜欢。
请先阅读文章Android源码分析:手把手带你分析 Glide的缓存功能
1. 背景
Glide实现内存 & 磁盘缓存是根据 图片的缓存
Key进行唯一标识
开发者为了降低成本 & 安全,往往会将图片存放在云服务器上
如 七牛云 等等。
为了保护 客户的图片资源,图片云服务器 会在图片
Url地址的基础上再加一个token参数
http://url.com/image.jpg?token=a6cvva6b02c670b0a
Glide加载该图片时,会使用加了
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参数
回看文章Android源码分析:手把手带你分析 Glide的缓存功能生成缓存
Key的代码
public class Engine implements EngineJobListener, MemoryCache.ResourceRemovedListener, EngineResource.ResourceListener { public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher, DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> 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 ... } <-- 分析19:getId() --> public class HttpUrlFetcher implements DataFetcher<InputStream> { ... private final GlideUrl glideUrl; // GlideUrl = 在上篇文章讲解 图片加载 第2步load()中传入图片url地址时,Glide在内部把图片url地址包装成一个GlideUrl对象 @Override public String getId() { return glideUrl.getCacheKey(); // ->>分析20 } <-- 分析20:getCacheKey() --> 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的图片缓存功能的使用问题进行讲解
关于Glide的相关文章阅读
Android源码分析:手把手带你分析 Glide的缓存功能
Android源码分析:这是一份详细的图片加载库Glide源码讲解攻略
Android图片加载库:最全面解析Glide用法
下面我将继续对
Glide的其他功能进行源码分析 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记
帮顶 / 评论点赞!因为你的鼓励是我写作的最大动力!
相关文章推荐
- Android 图片加载的那些事:为什么你的Glide 缓存没有起作用?
- Android中Glide加载图片并实现图片缓存
- android Glide加载图片缓存重复问题解决
- Android 平滑图片加载和缓存库 Glide
- 聊聊Android优秀的图片加载缓存的开源框架?UIL、Glide、Picasso
- Android平滑图片加载和缓存库 Glide 使用详解
- Android应用架构之Retrofit使用 RxJava 详解 jsoup Android 平滑图片加载和缓存库 Glide 使用详解
- Android中Glide加载库的图片缓存配置究极指南
- Android 平滑图片加载和缓存库 Glide 使用详解
- Android图片加载框架最全解析(三),深入探究Glide的缓存机制
- Android图片加载框架最全解析(三),深入探究Glide的缓存机制
- Android图片加载框架最全解析(三),深入探究Glide的缓存机制
- 比较强大 优秀的开源框架 :Android图片加载与缓存:Android Glide 的用法
- Android平滑图片加载和缓存库 Glide 使用详解
- Android 平滑图片加载和缓存库 Glide 使用详解
- Android中图片加载框架Glide解析3----深入探究Glide的缓存机制
- Android 平滑图片加载和缓存库 Glide 使用详解
- Android 图片加载和缓存库 Glide
- ym——Android(视频、图片)加载和缓存类库Glide
- Android图片加载与缓存开源框架:Android Glide