本文是我对自己掌握的网络缓存知识做一个总结,希望能对大家有所帮助,如有侵权,我改改就好了0.0
缓存过程
- 客户端-缓存-网络-拦截器
CacheControl类
- noCache 不使用缓存,全部走网络
- noStore 不使用缓存,也不存储缓存
- onlyIfCached 只使用缓存
- maxAge 设置最大失效时间,失效则不使用
- maxStale 设置最大失效时间,失效则不使用
- minFresh 设置有效时间
- FORCE_NETWORK 只走网络
- FORCE_CACHE 只走缓存
标识为 no-cache 的响应实际上是可以存储在本地缓存区中的。 只是在与原始服务器进行再验证之前,缓存不能将其提供给客户端使用,并不是不缓存的意思
依赖包
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.okhttp3:okhttp:3.3.1'
compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
compile 'com.zhy:okhttputils:2.6.2'
示例代码
public class RetrofitManager {
private static OkHttpClient mOkHttpClient;
private static final String TAG = "OkHttp";
//短缓存1分钟
public static final int CACHE_AGE_SHORT = 60;
//长缓存有效期为1天
public static final int CACHE_STALE_LONG = 60 * 60 * 24;
//自己的base_url
public static final String BASE_URL = "http://www.baidu.com";
private ApiServer apiServer;
private static RetrofitManager instance = new RetrofitManager();
public static RetrofitManager getInstance() {
return instance;
}
private RetrofitManager() {
initOkHttpClient();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(mOkHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiServer = retrofit.create(ApiServer.class);
}
private void initOkHttpClient() {
//日志拦截,使用okhttputils的HttpLoggingInterceptor,设置请求级别
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.e(TAG, message);
}
});
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//缓存的cookieJar负责管理cookies
com.zhy.http.okhttp.cookie.CookieJarImpl cookieJar = new com.zhy.http.okhttp.cookie.CookieJarImpl(new PersistentCookieStore(App.getInstance()));
//单例
if (mOkHttpClient == null) {
synchronized (OkHttpClient.class) {
if (mOkHttpClient == null) {
// 指定缓存路径,缓存大小10Mb
Cache cache = new Cache(new File(App.getInstance().getCacheDir(), "HttpCache"),
1024 * 1024 * 10);
mOkHttpClient = new OkHttpClient.Builder()
.cache(cache)
.addInterceptor(interceptor)
.addNetworkInterceptor(mCacheControlInterceptor)
.cookieJar(cookieJar)
.retryOnConnectionFailure(true)
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.build();
}
}
}
}
public static ApiServer build() {
return instance.apiServer;
}
// 响应头拦截器,用来配置缓存策略
private Interceptor mCacheControlInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!NetUtils.isConnected(App.getInstance())) {
//没网时只使用缓存
//自定义请求头,可以在响应头对请求头的header进行拦截,配置不同的缓存策略
request = request.newBuilder()
.header("head-request", request.toString())
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
Response response = chain.proceed(request);
if (NetUtils.isConnected(App.getInstance())) {
//有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置
Log.e("Interceptor", "response: " + response.toString());
//添加头信息,配置Cache-Control
//removeHeader("Pragma") 使缓存生效
return response.newBuilder()
.header("Cache-Control", "public, max-age=" + CACHE_AGE_SHORT)
.removeHeader("Pragma")
.build();
} else {
Log.e("Interceptor", "net not connect");
return response.newBuilder()
.header("Cache-Control", "public,only-if-cached, max-stale=" + CACHE_STALE_LONG)
.removeHeader("Pragma")
.build();
}
}
};
}
总结
缓存设置了也不一定生效,因为设置缓存保存下来是一个异步的过程,可能你请求网络保存缓存还没成功就进行了第二次请求,这样缓存就没生效了,一般只有get请求可以设置缓存,post请求无法被缓存,一般的显示列表信息或者不需要频繁刷新的页面可以设置get请求以及缓存,不然也不是很必要,根据缓存策略就好,比如希望用户离线还可以查看一定的页面信息。