Retrofit v2.4.0未发送If-Modified-Since请求头,缓存失效求助
看起来你已经做了基础的缓存配置,但OkHttp的缓存行为有几个容易被忽略的细节,我们一步步来排查:
1. 日志拦截器位置导致你看不到实际发送的请求头
你当前使用的是addInterceptor(logging)——这是应用拦截器,它只会记录你最初构建的请求,不会显示OkHttp内部拦截器(比如缓存拦截器)对请求的修改。而If-Modified-Since头是由OkHttp的缓存拦截器在网络请求阶段添加的,所以你需要把日志拦截器添加到网络拦截器中才能看到实际发送到服务器的请求:
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.HEADERS); Cache cache = new Cache(getApplication().getCacheDir(), 30 * 1024 * 1024); httpClient = new OkHttpClient.Builder() .cache(cache) .addNetworkInterceptor(logging) // 切换为网络拦截器 .build();
切换后,你就能看到缓存拦截器是否真的添加了If-Modified-Since头到请求里。
2. 确认缓存是否被正确存储
服务器已经返回了Last-Modified头,但你需要确认第一次请求后,响应是否被缓存了。可以通过以下代码检查缓存条目:
Request request = new Request.Builder() .url("http://someserver:8080/model/modelId") .build(); Cache.Entry entry = cache.get(request); if (entry != null) { Log.d("Cache", "Last-Modified from cache: " + entry.lastModified()); } else { Log.d("Cache", "No cache entry found"); }
如果没有缓存条目,可能是缓存目录权限问题、缓存大小设置不足,不过你的响应头是private,这是允许缓存的,所以这个可能性较低。
3. 强制OkHttp进行缓存验证
如果OkHttp认为缓存还“新鲜”,它可能直接返回缓存而不发送请求到服务器。由于你的响应头没有设置max-age,OkHttp会使用启发式缓存策略(默认是响应年龄的10%)。如果你希望每次请求都发送If-Modified-Since进行验证,可以给请求添加Cache-Control: max-age=0头:
在Retrofit接口方法里添加:
@GET("model/modelId") @Headers("Cache-Control: max-age=0") Call<YourModel> getModel(@Path("modelId") String modelId);
这个头会告诉OkHttp:缓存已经过期,必须向服务器验证缓存的有效性,此时就会自动带上If-Modified-Since头。
总结
最可能的原因是你用了应用拦截器,看不到实际发送的If-Modified-Since头。先切换到网络拦截器查看真实请求,再根据情况调整缓存策略即可。
内容的提问来源于stack exchange,提问作者Robert

