Picasso 2.8中如何正确失效图片URL缓存?
问题
应用使用Picasso 2.8加载头像,核心代码如下:
Picasso.get() .load(Constant.getInstance().MERCHANT.getProfPic()) .resize(width, width) .centerInside() .placeholder(R.drawable.avatar) .error(R.drawable.avatar) .into(profPicView);
问题点:Constant.getInstance().MERCHANT.getProfPic()的URL固定不变,但图片内容已更新,Picasso基于URL缓存的机制导致始终显示旧头像。尝试过以下方法均未解决:
- 头像上传成功后调用
Picasso.get().invalidate(...)清除缓存再重新加载 - 加载时添加
networkPolicy(NetworkPolicy.NO_CACHE)和memoryPolicy(MemoryPolicy.NO_CACHE) - 使用
stableKey()配合invalidate()
其中上传后尝试清除缓存的完整代码示例:
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest( Request.Method.POST, String.format("%s/v1/documents/cashierapp/%s", serverurl, Constant.getInstance().MERCHANT.getMobile()), postData, response -> { Trace.i("ProfileImgHttpPostTask", response.toString()); Constant.getInstance().VolleyParams.remove("Authorization"); Constant.getInstance().VolleyParams.put("Authorization", Constant.getInstance().MERCHANT.getToken()); // 尝试清除旧头像缓存 Picasso.get().invalidate(Constant.getInstance().MERCHANT.getProfPic()); Picasso.get() .load(Constant.getInstance().MERCHANT.getProfPic()) .resize(width, width) .centerInside() .placeholder(R.drawable.avatar) .error(R.drawable.avatar) .into(profPicView); }, error -> { Constant.getInstance().VolleyParams.remove("Authorization"); Constant.getInstance().VolleyParams.put("Authorization", Constant.getInstance().MERCHANT.getToken()); Trace.i("ProfileImgHttpPostTask", "HTTP " + error.networkResponse.statusCode + "\n" + new String(error.networkResponse.data, StandardCharsets.UTF_8)); } ) { @Override public Map<String, String> getHeaders() { Map<String, String> params = Constant.getInstance().VolleyParams; params.put("appid", CashierApp.getInstance().appid); params.put("Authorization", String.format("Bearer %s", CashierApp.getInstance().token)); return params; } }; jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy( 30000, 1, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)) .setShouldCache(false) .setShouldRetryServerErrors(false) .setShouldRetryConnectionErrors(true); Constant.getInstance().getQueue().add(jsonObjectRequest);
正确处理方式
方法1:给URL添加唯一标识参数(推荐)
Picasso的缓存完全基于URL,只要URL变化就会重新请求新资源。在头像上传成功后,给原URL拼接一个唯一参数(比如更新时间戳、后端返回的版本号):
// 上传成功后生成唯一标识(可以用当前时间戳,或者从接口返回的更新标识) long updateMarker = System.currentTimeMillis(); String updatedAvatarUrl = Constant.getInstance().MERCHANT.getProfPic() + "?v=" + updateMarker; // 更新MERCHANT中的头像URL,确保后续所有加载逻辑都用新URL Constant.getInstance().MERCHANT.setProfPic(updatedAvatarUrl); // 重新加载头像 Picasso.get() .load(updatedAvatarUrl) .resize(width, width) .centerInside() .placeholder(R.drawable.avatar) .error(R.drawable.avatar) .into(profPicView);
每次更新头像都更换参数值,就能彻底绕过缓存问题,同时不影响其他图片的缓存效率。
方法2:强制清除Picasso磁盘缓存(不推荐频繁使用)
如果无法修改URL,可以直接清除Picasso的整个磁盘缓存,但这会清空所有图片缓存,影响整体加载性能,仅适合特殊场景:
// 清除磁盘缓存必须在子线程执行 new Thread(() -> { try { Picasso.get().cache.clear(); } catch (IOException e) { e.printStackTrace(); } // 回到主线程重新加载头像 runOnUiThread(() -> { Picasso.get() .load(Constant.getInstance().MERCHANT.getProfPic()) .resize(width, width) .centerInside() .placeholder(R.drawable.avatar) .error(R.drawable.avatar) .into(profPicView); }); }).start();
方法3:调整服务器缓存策略
检查服务器返回图片时的Cache-Control响应头,如果设置了过长的max-age或者immutable,会导致客户端缓存无法及时失效。可以让后端修改图片接口的缓存配置,比如设置Cache-Control: no-cache或者较短的有效期,确保客户端能主动校验资源是否更新。
内容的提问来源于stack exchange,提问作者anta40
相关产品推荐
相关产品推荐

