okhttp3.4.1+retrofit2.1.0实现离线缓存
关于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实现离线缓存相关推荐
- 百度离线地图API2.0 百度离线地图api,已经修改源码
百度离线地图API2.0 百度离线地图api,已经修改源码,绕过服务端验证,除了路书等需要服务端数据支持的功能外,其余功能已经全部实现,包括常用的:地图示例.地图控件添加.覆盖物添加.信息窗口展示等等 ...
- gprMax3.0极速离线安装教程
gprMax3.0极速离线安装教程 简介 一.具体安装步骤 1.安装anaconda 2.解压百度网盘中的gprMax文件到对应文件夹 二.测试是否安装成功 简介 探地雷达研究方向目前已经成为了一个研 ...
- okhttp离线缓存_Android改造OkHttp离线缓存
okhttp离线缓存 In this tutorial, we'll be discussing and implementing Offline caching in our android app ...
- 关于域用户的离线缓存登录知识分享
关于域用户的离线缓存登录知识分享 微软设计缓存登录的目的? 缓存登录主要是为了解决当公司域控制器发生故障联系不上DC或用户拿笔记本电脑回家不拔×××的情况下,依然能够登录到系统,进行办公.如果用户登录 ...
- 【转载】基于AFNetWorking3.0的图片缓存分析
原文出处:Yasin的简书 http://www.jianshu.com/p/b1045c3fc8d0 图片在APP中占有重要的角色,对图片做好缓存是重要的一项工作. [TOC] 理论 不喜欢理论的可 ...
- 离线缓存占内存吗_彻底弄懂浏览器缓存策略
浏览器缓存策略对于前端开发同学来说不陌生,大家都有一定的了解,但如果没有系统的归纳总结,可能三言两语很难说明白,甚至说错,尤其在面试过程中感触颇深,很多候选人对这类基础知识竟然都是一知半解,说出几个概 ...
- html开启页面离线缓存,HTML5 离线缓存
离线缓存 applicationCache 第一次加载后将数据缓存,如果没有清除缓存,下一次没有网络也能加载. 使用 1. 使用 manifest 属性,引入 .appcache 文件 每个指定了 m ...
- javascript中本地储存、离线缓存、地理定位、网络状态
本地储存: 实际开发中某些内容是不需要放到服务器中,而是放到了浏览器中,需要的时候可以快速的访问,甚至页面刷新也可能不会丢失数据,容量较大:这里介绍两种数据存储方式:sessionStorage约5M ...
- 使用 jQuery Mobile 与 HTML5 开发 Web App (十七) —— HTML5 离线缓存
本文要介绍的,是 HTML5 离线网络应用程序的特性,离线网络应用程序在 W3C 中的实际名称是 "Offline Web applications" ,也称离线缓存.当用户打开浏 ...
- HTML5(3) -- 离线缓存与客户端存储总结
1.离线检测 可以使用navigator.onLine属性来检测 <!DOCTYPE html> <html lang="en"><head>& ...
最新文章
- 结构光测距相位差_ROHM确立新型VCSEL模块技术 有助于提高测距精度
- php入门时间,php入门教程(二十一) php日期与时间函数
- 【下载】推荐一款免费的人脸识别SDK
- PHP中如何实现 “在页面中一边执行一边输出” 的效果
- 使用Github(创建仓库、仓库主页说明)
- Android简单实现BroadCastReceiver广播机制
- 基于UDP的组播网络程序
- swift button一些简单设置
- word List 41
- hibernate配置详情2(Dept.hbm.xml)
- 在Kafka中发布订阅模型
- php min命令,php min函数怎么用?
- 基于任务编程_如何理解任何编程任务
- Ubuntu ufw防火墙常见命令
- EasyUI+MVC+EF简单用户管理Demo(问题及解决)
- matlab 图片最多显示几张_matlab 如何一次显示多个图像,subplot不合适
- backbone js学习笔记之第二篇Model层
- ubuntu锐捷校园网
- 图像加密--chua's chaos and baker's transformation
- JavaScript加法运算