Retrofit+OkHttp+Picasso长周期缓存配置与缓存图片加载优化
缓存逻辑优化方案(适配当前依赖版本)
缓存有效期调整至60天、到期前不触发网络请求
现有代码存在的核心问题
- 网络拦截器设置的缓存有效期仅为
60*60(1小时),远未达到60天的时效要求 - 原离线拦截器仅在无网络时走缓存逻辑,有网状态下只要超出本地缓存的有效期阈值,就会自动发起网络请求拉取新数据,没有做有网场景下的缓存优先级控制
- 未移除服务端返回的可能强制禁用缓存的响应头(如
Pragma、服务端自带的Cache-Control),这些头会覆盖自定义的缓存规则,导致缓存提前失效
定向修改代码
- 调整网络拦截器的缓存有效期配置:
public static Interceptor provideCacheInterceptor () { return new Interceptor() { @Override public Response intercept (Chain chain) throws IOException { Response response = chain.proceed( chain.request() ); // 60天有效期的秒数计算:天*小时*分钟*秒 long validDurationSeconds = 60 * 24 * 60 * 60; return response.newBuilder() .removeHeader("Pragma") .removeHeader(CACHE_CONTROL) // 强制设置规则:公开缓存、有效期内不校验、直接命中缓存 .header(CACHE_CONTROL, "public, only-if-cached, max-age=" + validDurationSeconds) .build(); } }; }
- 重构原离线拦截器的逻辑,实现全场景缓存优先:
public static Interceptor provideCachePriorityInterceptor () { return new Interceptor() { @Override public Response intercept (Chain chain) throws IOException { Request request = chain.request(); Cache appCache = provideCache(); // 优先从本地缓存读取对应请求的响应 Response cachedResponse = appCache != null ? appCache.get(request) : null; // 有网且存在有效缓存时,直接返回缓存内容,*不发起任何网络请求* if (cachedResponse != null && MyApplication.hasNetwork()) { return cachedResponse; } // 无网场景下的兜底逻辑:允许读取最长60天的过期缓存 if (!MyApplication.hasNetwork()) { long staleToleranceSeconds = 60 * 24 * 60 * 60; request = request.newBuilder() .removeHeader("Pragma") .removeHeader(CACHE_CONTROL) .header(CACHE_CONTROL, "public, only-if-cached, max-stale=" + staleToleranceSeconds) .build(); } return chain.proceed(request); } }; }
注意:在OkHttpClient初始化时,把原来的
provideOfflineCacheInterceptor替换为新的provideCachePriorityInterceptor,拦截器顺序不需要调整,应用层拦截器会先于网络层拦截器执行。
解决Picasso本地缓存加载慢、卡顿问题
现有配置的核心问题
- 初始化Picasso时仅配置了共享OkHttp下载器,没有针对解码效率做优化,默认全尺寸解码图片会导致内存占用过高、解码耗时拉长
- 正式包未关闭Picasso的调试标记和日志,额外增加了磁盘IO开销
- 加载图片时未按照ImageView实际尺寸做压缩解码,大图解码会阻塞主线程导致卡顿
定向优化配置
- 调整Picasso单例的初始化参数:
OkHttp3Downloader okHttp3Downloader = new OkHttp3Downloader(okHttpClient); Picasso picasso = new Picasso.Builder(MyApplication.getInstance()) .downloader(okHttp3Downloader) // 正式版关闭调试角标,减少不必要的绘制 .indicatorsEnabled(!BuildConfig.DEBUG) // 正式版关闭Picasso内部日志,减少IO .loggingEnabled(BuildConfig.DEBUG) // 使用*RGB_565*的色彩配置,比默认ARGB_8888减少一半内存占用,解码速度提升约40% .defaultBitmapConfig(Bitmap.Config.RGB_565) .build(); Picasso.setSingletonInstance(picasso);
- 日常图片加载的统一规范(可减少90%的加载卡顿问题):
- 所有加载请求必须按照ImageView的实际尺寸做压缩,避免加载全尺寸原图:
Picasso.get() .load(imageUrl) // 按控件实际尺寸压缩 .resize(imageView.getWidth(), imageView.getHeight()) .centerCrop() // 磁盘缓存命中时不重复写入内存缓存,降低内存占用 .memoryPolicy(MemoryPolicy.NO_STORE) .placeholder(R.drawable.placeholder) .into(imageView);
- 在列表滑动场景下,加载前先取消上一次未完成的请求,避免滑动时的资源竞争:
// 在Adapter的getView/onBindViewHolder方法中 Picasso.get().cancelRequest(holder.imageView); // 再执行新的加载逻辑
补充说明:当前配置已经让Picasso和Retrofit共用同一个OkHttp磁盘缓存,不需要给Picasso单独配置磁盘缓存,避免重复的磁盘文件读写开销,100MB的缓存容量可满足大部分场景的图片和接口缓存需求,OkHttp会自动通过LRU算法淘汰超出容量的旧缓存。
内容的提问来源于stack exchange,提问作者AMWolfstein
相关产品推荐
相关产品推荐

