Retrofit2实现缓存、离线缓存、在线缓存及@headers控制缓存时间

本文转自: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

你可能感兴趣的:(Retrofit2)