关于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() {
@Override
public 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() {
@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;
}
};

*注意:

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;
// }
// }; //缓存拦截器,统一缓存60s
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()) {
int maxAge = 60*60*24*2;//缓存失效时间,单位为秒
return response.newBuilder()
.removeHeader("Pragma")//清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效
.header("Cache-Control", "public ,max-age=" + maxAge)
.build();
}
return response;
}
};
}

okhttp3.4.1+retrofit2.1.0实现离线缓存的更多相关文章

  1. Xamarin For Visual Studio 3.0.54.0 完整离线破解版

    Xamarin For Visual Studio 3.0.54.0 完整离线破解版 Xamarin For Visual Studio就是原本的Xamarin For Android 以及 Xama ...

  2. HTML5离线缓存(Application Cache)

    HTML5离线缓存又名Application Cache,是从浏览器的缓存中分出来的一块缓存区,要想在这个缓存中保存数据,可以使用一个描述文件(manifest file),列出要下载和缓存的资源. ...

  3. HTML5 离线缓存管理库

    一.HTML5离线缓存技术 支持离线缓存是HTML5中的一个重点,离线缓存就是让用户即使在断网的情况下依然可以正常的运行应用.传统的本地存储数据的方式有 localstorage,sessionsto ...

  4. HTML5离线缓存问题

    HTML5离线缓存问题 1.应用程序缓存 什么是应用程序缓存(Application Cache)? HTML5 引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连接时进行访问. ...

  5. HTML5离线缓存

    参考文档:http://www.w3cschool.cc/html/html5-app-cache.html HTML5 应用程序缓存 又称离线缓存 ,即使断线了,刷新后也还是缓存了原来的页面,不会4 ...

  6. Html5离线缓存详细讲解

    离线缓存是Html5新特性之一,简单理解就是第一次加载后将数据缓存,在没有清除缓存前提下,下一次没有网络也可以加载,用在静态数据的网页或游戏比较好用.当然,Html5新的特性都不是所有浏览器都能支持的 ...

  7. 使用 jQuery Mobile 与 HTML5 开发 Web App —— HTML5 离线缓存

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

  8. HTML5 manifest离线缓存

    一.基本概念 离线缓存是HTML5新引入的技术,能够让你的Web应用程序指定哪些文件可以缓存在本地,使得你的网络断开时依然可以通过本地的缓存来进行访问浏览. 二.使用方法 1. MIME type 声 ...

  9. iOS开发--基于AFNetWorking3.0的图片缓存分析

    图片在APP中占有重要的角色,对图片做好缓存是重要的一项工作.[TOC] 理论 不喜欢理论的可以直接跳到下面的Demo实践部分 缓存介绍 缓存按照保存位置可以分为两类:内存缓存.硬盘缓存(FMDB.C ...

随机推荐

  1. Cisco HSRP 配置方法(热备份路由协议)配置实例

    转裁于51CTO.http://www.mamicode.com/info-detail-862350.html HSRP----热备份路由协议 思科私有协议,与VRRP 虚拟路由协议 相近,(国际标 ...

  2. Java 的布局管理器GridBagLayout的使用方法【图文说明】

    https://www.cnblogs.com/taoweiji/archive/2012/12/14/2818787.html GridBagLayout是java里面最重要的布局管理器之一,可以做 ...

  3. 在 Virtual Box 中为 CentOS7 mini 配置双网卡

    1. 配置过程 1.1 需求分析 要同时满足虚拟机访问互联网和远程连接,需要配置两块网卡. 一块为 NAT 网络,这块用来访问互联网. 另一块为 Host-Only 网络,进行远程连接.   1.2 ...

  4. 1001.A+B Format(10)

    1001.A+B Format(20) github链接:[example link](https://github.com/wgc12/object-oriented 1.对题目的理解: 首先这道题 ...

  5. 解决ThinkPHP中开启调试模式无法加载模块的问题。

    刚开始学习ThinkPHP就遇到这种问题,还是自己粗心. 错误如下: 原因:开启调试模式,区分大小写的,要把模块名首字母大写就OK了.也就是: [plain] view plain copy http ...

  6. swift类型擦除的定义-swift的类型擦除只是一个类型高低阶转换的游戏。

    所谓swift的类型擦除是指: moand转换: 通过技术手段(通常是包装器),将具体类型的类型信息擦除掉了,只将类型的(某一个侧面的)抽象信息(通常指的是类型尊从的协议.接口.或基类)暴露出来. A ...

  7. weex+vue2.x 踩坑实录(不定期更新)

    执行 npm start 显示空白页面 这个是开始使用weex就出现的一个大坑,说实话对新手真的很不友好. 1.打开控制台显示:Cannot assign to read only property ...

  8. vue之常用指令

    事件缩写 v-on:click= 简写方式 @click= 事件对象$event <!DOCTYPE html> <html lang="en"> < ...

  9. TIOBE 11月编程语言榜:Go逆袭,Python势头很猛!

    导读 离 TIOBE 宣布 2018 年的编程语言只有2个月了.目前来看,有 5 个候选对象,它们都是来自前五名的:Java.C.C++.Python.Visual Basic.NET.每年我们都希望 ...

  10. 一,ESP8266下载和刷固件(基于Lua脚本语言)

    用自己的小板测试...... 安排上呢 一, ESP8266下载和刷固件(Lua开发----体验一下lua开发的魅力所在) 二, 控制一个灯亮灭 三, TCP服务器 四, TCP客户端 五, UDP ...