项目中会有这种需求,一个图片链接没变,但是已经是另外一个图了,比如用户的头像,别人的头像修改了,本机的头像也要跟着改动,但是一般本地的图片都会做缓存,如果没有一个机制,来通知本地的图片已经过期的话,我们无法知道什么时候用缓存,什么时候该更新。简单粗暴的方法就是,不做本地缓存,每次都从网络加载,不过这样会耗费比较多的流量。
既然要用缓存,还要随时能更新,能想到的一个可行的办法就是,每次都要请求,但是如果图片不是最新的就不加载了,使用缓存。
Http的请求有这样一个header,If-Modified-Since,其值为上次服务器返回的响应头中的Last-Modified。Last-Modified是服务器标识的资源的最近修改时间,服务器可以根据If-Modified-Since来判断客户端的资源是不是最新,如果是最新的,返回304,并且没有响应体;如果不是最新的,返回200,此时可以记录Last-Modified的值,作为下次请求的If-Modified-Since。
/**
* url不变而图片变化的情况,使用此类加载
* Created by feng on 2018/5/15.
*/
public class GlideUtil {
private static OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(5L, TimeUnit.SECONDS)
.build();
// 目前将lastModified保存在内存中,也就是每次打开app都会刷新图片,如有必要,可以保存在本地磁盘中
private static HashMap<String,String> timeMap = new HashMap<>();
public static void load(Context context, String url, ImageView imageView,int defaultResId){
String lastModified = timeMap.get(url);
if (lastModified == null) lastModified = "";
request(context,url,imageView,lastModified,defaultResId);
}
private static void request(final Context context
, final String url
, final ImageView imageView
, final String lastModified
, final int defaultResId){
Request request = new Request.Builder()
.addHeader("If-Modified-Since",lastModified)
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
UIHandler.post(new Runnable() {
@Override
public void run() {
Glide.with(context)
.load(url)
.signature(new StringSignature(lastModified))
.error(defaultResId)
.into(imageView);
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
int code = response.code();
StringSignature signature = null;
if (code == 304){
// 说明图片没变
signature = new StringSignature(lastModified);
}else if(code /100 == 2){
// 图片变了
final String newTime = response.header("Last-Modified");
timeMap.put(url,newTime);
signature = new StringSignature(newTime);
}
final StringSignature stringSignature = signature;
UIHandler.post(new Runnable() {
@Override
public void run() {
DrawableTypeRequest<String> load = Glide.with(context)
.load(url);
if(stringSignature != null){
load.signature(stringSignature)
.error(defaultResId)
.into(imageView);
}else{
load.error(defaultResId)
.into(imageView);
}
}
});
}
});
}
}
使用的话,直接调用
GlideUtil.load(context,imgUrl,imageView,defaultResId);