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

参考来自 使用Retrofit和Okhttp实现网络缓存。

由于retrofit和okhttp都已经更新,在某些细节上参考的那篇博客已经不适用了,而且那篇博客并没有介绍@headers如何具体使用。

这篇博客完整的介绍了怎么用interceptor实现retrofit的缓存,学习时需要注意一下自己的retrofit,okhttp的版本,因为不同版本的某些方法名是不同的,在文章末尾我把现在使用的版本贴上了。

由于缓存需要的动态变化比较强,这次以北京时间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 {
            //获取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是用的上一篇博客的工程,已经封装了一部分,所以直接拿来用可能用不了。还有如果okhttp和retrofit方法不一样,参考我的包或者自行修改。

 compile 'com.squareup.retrofit2:retrofit:2.0.2'
 //5月23号更新:由于retrofit2内部已经集成okhttp3,所以不需要再依赖Okhttp了
 //compile 'com.squareup.okhttp3:okhttp:3.2.0'
 //compile 'io.reactivex:rxjava:1.1.3'

转载请注明出处–>http://blog.csdn.net/adzcsx2

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值