关于Retrofit+OkHttp的强大这里就不多说了,还没了解的同学可以自行去百度。这篇文章主要讲如何利用Retrofit+OkHttp来实现一个较为简单的缓存策略:
即有网环境下我们请求数据时,如果没有缓存或者缓存过期了,就去服务器拿数据,并且将新缓存保存下来,如果有缓存而且没有过期,则直接使用缓存。无网环境下我们请求数据时,缓存没过期则直接使用缓存,缓存过期了则无法使用,需要重新联网获取服务器数据。

缓存处理还是很有必要的,它有效的减少服务器负荷,降低延迟提升用户体验,同时也方便用户即使在没网络的情况下也能使用APP。

之前一直有一个疑惑,既然Retrofit已经是对OkHttp的一个封装了,为什么还一直说Retrofit+OkHttp要一起搭配使用,后来才知道其实OKHttp很重要的一个作用,就是对一些网络请求的配置,例如连接超时,读取超时,以及一些缓存配置等。

一、添加依赖
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'

二、配置OkHttpClient(设置缓存路径和缓存文件大小)

File httpCacheDirectory = new File(Environment.getExternalStorageDirectory(), "HttpCache");//这里为了方便直接把文件放在了SD卡根目录的HttpCache中,一般放在context.getCacheDir()中
int cacheSize = 10 * 1024 * 1024;//设置缓存文件大小为10M
Cache cache = new Cache(httpCacheDirectory, cacheSize);
httpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS)//设置连接超时.readTimeout(10, TimeUnit.SECONDS)//读取超时.writeTimeout(10, TimeUnit.SECONDS)//写入超时.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)//添加自定义缓存拦截器(后面讲解),注意这里需要使用.addNetworkInterceptor.cache(cache)//把缓存添加进来.build();

三、配置Retrofit

retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(httpClient)//把OkHttpClient添加进来
                .addConverterFactory(GsonConverterFactory.create()).build();

四、编写拦截器

  我们知道其实Retrofit+OkHttp的缓存主要通过拦截器实现,所以主要做的功夫也在拦截器里面。

 static Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();//网上很多示例代码都对在request请求前对其进行无网的判断,其实无需判断,无网自动访问缓存
//            if(!NetworkUtil.getInstance().isConnected()){
//                request = request.newBuilder()
//                        .cacheControl(CacheControl.FORCE_CACHE)//只访问缓存
//                        .build();
//            }Response response = chain.proceed(request);if (NetworkUtil.getInstance().isConnected()) {int maxAge = 60;//缓存失效时间,单位为秒return response.newBuilder().removeHeader("Pragma")//清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效.header("Cache-Control", "public ,max-age=" + maxAge).build();} else {//这段代码设置无效
//                int maxStale = 60 * 60 * 24 * 28; // 无网络时,设置超时为4周
//                return response.newBuilder()
//                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
//                        .removeHeader("Pragma")
//                        .build();
            }return response;}};

到这里,其实已经可以实现了我们开头所说的缓存效果了。

  但是,上面设置的每个接口缓存时间都一样,例如我现在想让不同接口的缓存数据失效时间都不一样,甚至有些接口不缓存数据,应该怎么做呢?其实也很简单

首先我们只需要在接口前面添加@Headers参数(max-age代表缓存时间,单位为秒,示例中表示缓存失效时间为60s,想要多少时间可以自行设置),不设置@Headers参数则不进行缓存。

    @Headers("Cache-Control:public ,max-age=60")@GET("getBusiness.action")//商店信息Call<RestaurantInfoModel> getRestaurantInfo(@Query("userId") String userId,@Query("businessId") String businessId);

同时,我们的缓存拦截器也要做下简单的修改(去掉了之前的注释代码)

    static Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();Response response = chain.proceed(request);if (NetworkUtil.getInstance().isConnected()) {//获取头部信息String cacheControl =request.cacheControl().toString();return response.newBuilder().removeHeader("Pragma")//清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效.header("Cache-Control", cacheControl).build();}return response;}};

*注意:

1.只能缓存Get请求的接口,不能缓存Post请求的接口

2.OkHttpClient需要用.addNetworkInterceptor添加缓存拦截器,不能使用.addInterceptor,也无需两者同时使用。

3.此方法无需服务器端任何操作,适用于服务器端没有其他缓存策略,如果服务器端有自己的缓存策略代码应该做相应的修改,以适应服务器端。

附上所有代码:

/*** 简单封装的Retroit初始化类*/
public class initRetrofit {private static String baseUrl = "http://202.171.212.154:8080/hh/";private static OkHttpClient httpClient;private static Retrofit retrofit;public static Retrofit initRetrofit() {//缓存路径和大小File httpCacheDirectory = new File(Environment.getExternalStorageDirectory(), "HttpCache");int cacheSize = 10 * 1024 * 1024;Cache cache = new Cache(httpCacheDirectory, cacheSize);//日志拦截器HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);httpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS)//设置连接超时.readTimeout(10, TimeUnit.SECONDS)//读取超时.writeTimeout(10, TimeUnit.SECONDS)//写入超时.addInterceptor(interceptor)//添加日志拦截器.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)//添加缓存拦截器.cache(cache)//把缓存添加进来
                .build();retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(httpClient).addConverterFactory(GsonConverterFactory.create()).build();return retrofit;}public static RetrofitAPI getService() {return initRetrofit().create(RetrofitAPI.class);}//    //缓存拦截器,不同接口不同缓存
//    static Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
//        @Override
//        public Response intercept(Chain chain) throws IOException {
//
//            Request request = chain.request();
//            Response response = chain.proceed(request);
//
//            if (NetworkUtil.getInstance().isConnected()) {
//                String cacheControl =request.cacheControl().toString();
//                return response.newBuilder()
//                        .removeHeader("Pragma")//清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效
//                        .header("Cache-Control", cacheControl)
//                        .build();
//            }
//            return response;
//        }
//    };//缓存拦截器,统一缓存60sstatic Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();Response response = chain.proceed(request);if (NetworkUtil.getInstance().isConnected()) {int maxAge = 60*60*24*2;//缓存失效时间,单位为秒return response.newBuilder().removeHeader("Pragma")//清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效.header("Cache-Control", "public ,max-age=" + maxAge).build();}return response;}};
}

转载于:https://www.cnblogs.com/cxk1995/p/5996586.html

okhttp3.4.1+retrofit2.1.0实现离线缓存相关推荐

  1. 百度离线地图API2.0 百度离线地图api,已经修改源码

    百度离线地图API2.0 百度离线地图api,已经修改源码,绕过服务端验证,除了路书等需要服务端数据支持的功能外,其余功能已经全部实现,包括常用的:地图示例.地图控件添加.覆盖物添加.信息窗口展示等等 ...

  2. gprMax3.0极速离线安装教程

    gprMax3.0极速离线安装教程 简介 一.具体安装步骤 1.安装anaconda 2.解压百度网盘中的gprMax文件到对应文件夹 二.测试是否安装成功 简介 探地雷达研究方向目前已经成为了一个研 ...

  3. okhttp离线缓存_Android改造OkHttp离线缓存

    okhttp离线缓存 In this tutorial, we'll be discussing and implementing Offline caching in our android app ...

  4. 关于域用户的离线缓存登录知识分享

    关于域用户的离线缓存登录知识分享 微软设计缓存登录的目的? 缓存登录主要是为了解决当公司域控制器发生故障联系不上DC或用户拿笔记本电脑回家不拔×××的情况下,依然能够登录到系统,进行办公.如果用户登录 ...

  5. 【转载】基于AFNetWorking3.0的图片缓存分析

    原文出处:Yasin的简书 http://www.jianshu.com/p/b1045c3fc8d0 图片在APP中占有重要的角色,对图片做好缓存是重要的一项工作. [TOC] 理论 不喜欢理论的可 ...

  6. 离线缓存占内存吗_彻底弄懂浏览器缓存策略

    浏览器缓存策略对于前端开发同学来说不陌生,大家都有一定的了解,但如果没有系统的归纳总结,可能三言两语很难说明白,甚至说错,尤其在面试过程中感触颇深,很多候选人对这类基础知识竟然都是一知半解,说出几个概 ...

  7. html开启页面离线缓存,HTML5 离线缓存

    离线缓存 applicationCache 第一次加载后将数据缓存,如果没有清除缓存,下一次没有网络也能加载. 使用 1. 使用 manifest 属性,引入 .appcache 文件 每个指定了 m ...

  8. javascript中本地储存、离线缓存、地理定位、网络状态

    本地储存: 实际开发中某些内容是不需要放到服务器中,而是放到了浏览器中,需要的时候可以快速的访问,甚至页面刷新也可能不会丢失数据,容量较大:这里介绍两种数据存储方式:sessionStorage约5M ...

  9. 使用 jQuery Mobile 与 HTML5 开发 Web App (十七) —— HTML5 离线缓存

    本文要介绍的,是 HTML5 离线网络应用程序的特性,离线网络应用程序在 W3C 中的实际名称是 "Offline Web applications" ,也称离线缓存.当用户打开浏 ...

  10. HTML5(3) -- 离线缓存与客户端存储总结

    1.离线检测 可以使用navigator.onLine属性来检测 <!DOCTYPE html> <html lang="en"><head>& ...

最新文章

  1. 结构光测距相位差_ROHM确立新型VCSEL模块技术 有助于提高测距精度
  2. php入门时间,php入门教程(二十一) php日期与时间函数
  3. 【下载】推荐一款免费的人脸识别SDK
  4. PHP中如何实现 “在页面中一边执行一边输出” 的效果
  5. 使用Github(创建仓库、仓库主页说明)
  6. Android简单实现BroadCastReceiver广播机制
  7. 基于UDP的组播网络程序
  8. swift button一些简单设置
  9. word List 41
  10. hibernate配置详情2(Dept.hbm.xml)
  11. 在Kafka中发布订阅模型
  12. php min命令,php min函数怎么用?
  13. 基于任务编程_如何理解任何编程任务
  14. Ubuntu ufw防火墙常见命令
  15. EasyUI+MVC+EF简单用户管理Demo(问题及解决)
  16. matlab 图片最多显示几张_matlab 如何一次显示多个图像,subplot不合适
  17. backbone js学习笔记之第二篇Model层
  18. ubuntu锐捷校园网
  19. 图像加密--chua's chaos and baker's transformation
  20. JavaScript加法运算

热门文章

  1. 信号与系统(二)——正交
  2. VC中ComboBox控件用法详解
  3. lu分解 百度百科
  4. AngularJS 简介
  5. 【网络协议】IP协议、ARP协议、RARP协议
  6. Mac---使用tree生成目录结构
  7. 在Mac下连接阿里云服务器
  8. 转:Raft一致性选举算法的ppt与视频
  9. 使用JavaParser进行java源码解析
  10. .sln文件和.suo文件的解释