APP图片缓存与Glide之signature的分析

1.图片缓存遇到的问题

在缓存网络图片的过程中,有一种情况是图片的地址不变,但图片发生了变化,如果只按照图片的地址进行缓存,在加载缓存中的图片时就会发生图片一直显示为旧图的现象。
App中修改用户头像的功能中,如果服务器存储头像的地址保持不变,加载缓存就会出现上述的情况。马上想到,当修改头像之后,马上将本地原头像的缓存清除,并加载新头像,此方法只是暂时解决了APP端头像的显示效果,如果在其他终端进行了头像修改,手机上并不能同步显示最新图片。

那么该如何获取最新的网络图片呢?显然不使用缓存是肯定可以显示最新的图片,但要使用缓存图片功能,又希望可以获取最新的图片,我们需要记录图片是否发生了变化,根据变化与否,选择是否更新缓存中的内容。
有人说下载图片之后,判断其SHA值是否相同,即可得知图片是否相同。然而,每次都要下载图片,再判断SHA值,还用缓存做什么,已经完全背道而驰。
好的做法是在服务器上加上图片是否改变的标识,在APP端存储该值,在加载缓存内容之前判断是否有改变,需要更新缓存内容。该标识可以使用时间戳,来记录图片更新时间,或使用累加数来记录标识。
,以上说的是处理自己的服务器上,数据可以增加字段的情况。如果只是单纯的加载网络上的图片,可以在图片下载之后,在APP中做标识,一段时间之内不更新,在一天或固定时间后检测标识并更新网络图片。比如一天更新一次,则可将日期作为标识。

2.Glide的简析

Glide作为一个优秀的加载图片库,提供了signature方法对图片进行标识,现针对安卓Glide-3.7.0进行简要分析。
Glide的一般调用方法为Glide.with(context).load(url).into(target);使用缓存时.diskCacheStrategy(DiskCacheStrategy. XXX)来指定缓存类型。
枚举类DiskCacheStrategy有两个属性,
</pre><pre name="code" class="java">private final boolean cacheSource;
private final boolean cacheResult;
//四个枚举值
/** Caches with both {@link #SOURCE} and {@link #RESULT}. */
ALL(true, true), //缓存原文件和处理后(如尺寸变化、类型转换) 的数据

/** Saves no data to cache. */
NONE(false, false), //不缓存

/** Saves just the original data to cache. */
SOURCE(true, false), //只缓存原文件

/** Saves the media item after all transformations to cache. */
RESULT(false, true); //只缓存处理后的数据

也可以通过.signature(Key signature)方法传入标识,来实现预期功能。传入参数为实现Key接口的类对象,Glide中有三个类StringSignature,MediaStoreSignature,EmptySignature.
构造方法StringSignature(String signature)中传入String,可以简单传入刚才说的时间戳进行标识。
构造方法MediaStoreSignature(String mimeType, long dateModified, int  orientation)可以传入图片的mimeType,修改时间,图片或视频的方向
当然也可以自定义类实现Key接口并复写其equals方法判断标识相同,及updateDiskCacheKey方法去更新本地缓存文件。
现在说说Glide加载图片的过程。
在into()方法(GenericRequestBuilder类中的方法)中创建了Request:
Request request = buildRequest(target);//创建GenericRequest实例
requestTracker.runRequest(request);//调用GenericRequest的begin方法

而在begin()方法中会调用onSizeReady(int width,int height)方法
此方法中调用engine.load方法开始加载图片
Engine类中load方法部分如下:
final String id = fetcher.getId();//当加载url图片时,id为图片地址
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
     loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
     transcoder, loadProvider.getSourceEncoder());//根据id,signature以及其他的信息生成key,用于缓存文件的key

EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);

EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);

DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,

        transcoder, diskCacheProvider, diskCacheStrategy, priority);

EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);

jobs.put(key, engineJob);

engineJob.addCallback(cb);
engineJob.start(runnable);

在runnable的run方法中调用decode()方法
private Resour
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值