Retrofit2实现离线缓存

这篇博客的实现相信如果会okhttp的都知道怎么做。写这篇的目的是为了记录一下用retrofit实现缓存,以及还有一个坑没有解决,期待找到解决方案。
由于缓存需要的动态变化比较强,这次以北京时间API为例。
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 {
            okhttp3.Response originalResponse = chain.proceed(chain.request());
            String cacheControl = originalResponse.header("Cache-Control");
            //如果cacheControl为空,就让他TIMEOUT_CONNECT秒的缓存,本例是5秒,方便观察
            if (cacheControl == null) {
                originalResponse = originalResponse.newBuilder()
                        .header("Cache-Control", "public, max-age=" + TIMEOUT_CONNECT)
                        .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的缓存。
我最终想实现的是:如果不加headers,cacheControl为空就不缓存,在ITime接口里加@Headers(Cache-Control:max-age=xx),就有xx秒缓存,加不过我一直奇怪的是在ITime里面加headers,在拦截器里面是拦截不到的,总是为空。我在拦截器里把header全部遍历了一遍,也没有。在拦截器里面 .header(“Cache-Control”, “public, max-age=” + TIMEOUT_CONNECT)之后,是有这个header的。
如果有朋友知道怎么解决,希望能告知我。或者是以后我找到了解决方案,我会重新更新这篇博客。

本篇博文的Demo是用的上一篇博客的工程,已经封装了一部分,所以直接拿来用可能用不了。还有如果okhttp和retrofit方法不一样,参考我的包或者自行修改。

 compile 'com.squareup.retrofit2:retrofit:2.0.2'
 compile 'com.squareup.okhttp3:okhttp:3.2.0'
 compile 'io.reactivex:rxjava:1.1.3'

你可能感兴趣的:(android,缓存,okhttp,retrofit,rxjava)