本文转自:http://blog.csdn.net/adzcsx2/article/details/51365548
参考文章: 使用Retrofit和Okhttp实现网络缓存
这篇博客完整的介绍了怎么用interceptor实现retrofit的缓存,学习时需要注意一下自己的retrofit,okhttp的版本,因为不同版本的某些方法名是不同的,在文章末尾我把现在使用的版本贴上了。
由于缓存需要的动态变化比较强,这次以北京时间API为例。
http://api.k780.com:88/?app=life.time&appkey=19292&sign=4684f7ddf14f1f63e1e312be09cb080e&format=json
返回结果:
{
"success": "1",
"result": { "timestamp": "1462873531", "datetime_1": "2016-05-10 17:45:31", "datetime_2": "2016年05月10日 17时45分31秒", "week_1": "2", "week_2": "星期二", "week_3": "周二", "week_4": "Tuesday" } }
interface:
public interface ITime {
@GET("/")
Observable<BeiJingTime> getTime(@Query("app") String app,@Query("appkey") String appkey,@Query("sign") String sign,@Query("format") String json);
}
retrofit配置:
//baseUrl
public static final String url_time = "http://api.k780.com:88";
private static Retrofit getRetrofit(String url) {
//缓存容量
long SIZE_OF_CACHE = 10 * 1024 * 1024; // 10 MiB
//缓存路径
String cacheFile = MyApplication.getContextObject().getCacheDir()+"/http";
Cache cache = new Cache(new File(cacheFile), SIZE_OF_CACHE);
//利用okhttp实现缓存
OkHttpClient client = new OkHttpClient.Builder()
//有网络时的拦截器
.addNetworkInterceptor(CachingControlInterceptor.REWRITE_RESPONSE_INTERCEPTOR)
//没网络时的拦截器
.addInterceptor(CachingControlInterceptor.REWRITE_RESPONSE_INTERCEPTOR_OFFLINE)
.cache(cache)
.build();
//返回retrofit对象
return new Retrofit.Builder().baseUrl(url)
.client(client)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
//获取ITime对象
public static ITime getITime() {
return getRetrofit(url_time).create(ITime.class);
}
用RxJava获取结果
HttpUtil.getITime().getTime("life.time","19292","4684f7ddf14f1f63e1e312be09cb080e","json")
.compose(RxHelper.io_main(MainActivity.this))
.subscribe(new RxSubscriber<Object>() {
@Override
public void _onNext(Object o) {
BeiJingTime time = (BeiJingTime) o;
tv.setText(time.getResult().getDatetime_2());
}
@Override
public void _onError(String msg) {
tv.setText(msg+"aaa");
}
});
Interceptor拦截器:
private static final int TIMEOUT_CONNECT = 5; //5秒
private static final int TIMEOUT_DISCONNECT = 60 * 60 * 24 * 7; //7天
public static final Interceptor REWRITE_RESPONSE_INTERCEPTOR = new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
//获取retrofit @headers里面的参数,参数可以自己定义,在本例我自己定义的是cache,跟@headers里面对应就可以了
String cache = chain.request().header("cache");
okhttp3.Response originalResponse = chain.proceed(chain.request());
String cacheControl = originalResponse.header("Cache-Control");
//如果cacheControl为空,就让他TIMEOUT_CONNECT秒的缓存,本例是5秒,方便观察。注意这里的cacheControl是服务器返回的
if (cacheControl == null) {
//如果cache没值,缓存时间为TIMEOUT_CONNECT,有的话就为cache的值
if (cache == null || "".equals(cache)) {
cache = TIMEOUT_CONNECT + "";
}
originalResponse = originalResponse.newBuilder()
.header("Cache-Control", "public, max-age=" + cache)
.build();
return originalResponse;
} else {
return originalResponse;
}
}
};
public static final Interceptor REWRITE_RESPONSE_INTERCEPTOR_OFFLINE = new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//离线的时候为7天的缓存。
if (!NetUtils.isConnected(MyApplication.getContextObject())) {
request = request.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale="+TIMEOUT_DISCONNECT)
.build();
}
return chain.proceed(request);
}
};
这样就实现了retrofit默认的缓存。
如果想要自己控制有网的时候的缓存时间。那么
public interface ITime {
//20秒缓存
@headers("cache:20")
@GET("/")
Observable<BeiJingTime> getTime(@Query("app") String app,@Query("appkey") String appkey,@Query("sign") String sign,@Query("format") String json);
}
值得注意的是
缓存时间不是固定的???这个原因我还没找到,昨天我写这篇博客的时候5秒的缓存就是5秒,今天来更新,5s的缓存没用了,然后我让他20秒,实际缓存时间为12秒。
具体原因暂时没找到,暂时提醒一下各位朋友,测试的时候最好把缓存时间写长一点。。
本篇博文的Demo:http://download.csdn.net/detail/jdsjlzx/9529124