Retrofit 2 缓存 - 拦截器链
Retrofit 2 caching - chain of interceptors
我需要实现 API 响应的基本缓存。我做了一个小游乐场项目,调用 GitHub API 并且缓存成功(我用 Charles 来验证)。但是,当我将此解决方案转移到我的目标项目时,缓存不再起作用。链中的多个拦截器可能是原因吗?
来自 playground 项目的代码(有效):
拦截器(目标项目相同):
public class CacheControlInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response.newBuilder()
.header("Cache-Control", "only-if-cached")
.build();
}
}
缓存和客户端声明:
long SIZE_OF_CACHE = 10 * 1024 * 1024; // 10 MB
final Cache cache = new Cache(new File(getCacheDir(), "retrofit_cache"), SIZE_OF_CACHE);
OkHttpClient.Builder client = new OkHttpClient.Builder().cache(cache);
client.networkInterceptors().add(new CacheControlInterceptor());
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/users/")
.addConverterFactory(GsonConverterFactory.create())
.client(client.build())
.build();
CacheControlInterceptor 的调试屏幕:
screen
来自目标项目的代码(不工作):
缓存和客户端声明:
private OkHttpClient provideOkHttpClient() {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder okhttpClientBuilder = new OkHttpClient.Builder();
okhttpClientBuilder.connectTimeout(30, TimeUnit.SECONDS);
okhttpClientBuilder.readTimeout(30, TimeUnit.SECONDS);
okhttpClientBuilder.writeTimeout(30, TimeUnit.SECONDS);
okhttpClientBuilder.addInterceptor(loggingInterceptor);
okhttpClientBuilder.addInterceptor(new JwtRenewInterceptor(getUserSession()));
okhttpClientBuilder.addInterceptor(new AutoLoginInterceptor(getUserSession()));
okhttpClientBuilder.addNetworkInterceptor(new CacheControlInterceptor());
long SIZE_OF_CACHE = 10 * 1024 * 1024; // 10 MB
final Cache cache = new Cache(new File(getCacheDir(), "retrofit_cache"), SIZE_OF_CACHE);
okhttpClientBuilder.cache(cache);
return okhttpClientBuilder.build();
}
CacheControlInterceptor 调试屏幕:screen
如果您想将一些 header 应用于所有使用 OkHttp 缓存的请求,您应该使用应用程序拦截器,而不是网络拦截器。否则,您不会为缓存机制提供 return 缓存响应的机会。
它在 OkHttp wiki 上有很好的说明
所以很可能在您的代码中发生的事情是您让 Cache
存储响应,但您从不使用它们,因为去往缓存的请求丢失 only-if-cached
header。
试试看
okhttpClientBuilder.addInterceptor(new CacheControlInterceptor());
其实这个错误是我对 http headers 的推理不当造成的。我认为方法 addHeader
或 header
只会添加键 Cache-Control
,然后添加值 only-if-cached
。然而,它只会增加价值!由于在我的目标项目的 API 中没有 header 键 Cache-Control
(与 GitHub API 中不同)因此没有值 only-if-cached
的位置被存储。
我需要实现 API 响应的基本缓存。我做了一个小游乐场项目,调用 GitHub API 并且缓存成功(我用 Charles 来验证)。但是,当我将此解决方案转移到我的目标项目时,缓存不再起作用。链中的多个拦截器可能是原因吗?
来自 playground 项目的代码(有效):
拦截器(目标项目相同):
public class CacheControlInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response.newBuilder()
.header("Cache-Control", "only-if-cached")
.build();
}
}
缓存和客户端声明:
long SIZE_OF_CACHE = 10 * 1024 * 1024; // 10 MB
final Cache cache = new Cache(new File(getCacheDir(), "retrofit_cache"), SIZE_OF_CACHE);
OkHttpClient.Builder client = new OkHttpClient.Builder().cache(cache);
client.networkInterceptors().add(new CacheControlInterceptor());
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/users/")
.addConverterFactory(GsonConverterFactory.create())
.client(client.build())
.build();
CacheControlInterceptor 的调试屏幕: screen
来自目标项目的代码(不工作):
缓存和客户端声明:
private OkHttpClient provideOkHttpClient() {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder okhttpClientBuilder = new OkHttpClient.Builder();
okhttpClientBuilder.connectTimeout(30, TimeUnit.SECONDS);
okhttpClientBuilder.readTimeout(30, TimeUnit.SECONDS);
okhttpClientBuilder.writeTimeout(30, TimeUnit.SECONDS);
okhttpClientBuilder.addInterceptor(loggingInterceptor);
okhttpClientBuilder.addInterceptor(new JwtRenewInterceptor(getUserSession()));
okhttpClientBuilder.addInterceptor(new AutoLoginInterceptor(getUserSession()));
okhttpClientBuilder.addNetworkInterceptor(new CacheControlInterceptor());
long SIZE_OF_CACHE = 10 * 1024 * 1024; // 10 MB
final Cache cache = new Cache(new File(getCacheDir(), "retrofit_cache"), SIZE_OF_CACHE);
okhttpClientBuilder.cache(cache);
return okhttpClientBuilder.build();
}
CacheControlInterceptor 调试屏幕:screen
如果您想将一些 header 应用于所有使用 OkHttp 缓存的请求,您应该使用应用程序拦截器,而不是网络拦截器。否则,您不会为缓存机制提供 return 缓存响应的机会。
它在 OkHttp wiki 上有很好的说明
所以很可能在您的代码中发生的事情是您让 Cache
存储响应,但您从不使用它们,因为去往缓存的请求丢失 only-if-cached
header。
试试看
okhttpClientBuilder.addInterceptor(new CacheControlInterceptor());
其实这个错误是我对 http headers 的推理不当造成的。我认为方法 addHeader
或 header
只会添加键 Cache-Control
,然后添加值 only-if-cached
。然而,它只会增加价值!由于在我的目标项目的 API 中没有 header 键 Cache-Control
(与 GitHub API 中不同)因此没有值 only-if-cached
的位置被存储。