【缓存策略】Retrofit+OkHttp实现缓存处理
来源:互联网 发布:淘宝上有铁匠铺吗 编辑:程序博客网 时间:2024/05/18 20:10
早先对于服务器数据缓存处理一般是本地SP或者Sqlite;现在网络请求改为Retrofit+OkHttp,OkHttp是有缓存策略的,
今天我们就来说怎么实现Retrofit与OkHttp的缓存实现。
使用缓存的目的
减少服务器负荷,降低延迟提升用户体验。复杂的缓存策略会根据用户当前的网络情况采取不同的缓存策略,比如在2g网络很差的情况下,提高缓存使用的时间;不用的应用、业务需求、接口所需要的缓存策略也会不一样,需要数据的实时性,采用缓存就是无意义!根据实际应用情况,制定自己的缓存策略。
Retrofit+OkHttp的缓存机制
在响应请求之后在 data/data/<包名>/cache 下建立一个response 文件夹,保持缓存数据。
这样我们就可以在请求的时候,如果判断到没有网络,自动读取缓存的数据。
同样这也可以实现,在我们没有网络的情况下,重新打开App可以浏览的之前显示过的内容。
也就是:判断网络,有网络,则从网络获取,并保存到缓存中,无网络,则从缓存中获取。
这样我们就可以在请求的时候,如果判断到没有网络,自动读取缓存的数据。
同样这也可以实现,在我们没有网络的情况下,重新打开App可以浏览的之前显示过的内容。
也就是:判断网络,有网络,则从网络获取,并保存到缓存中,无网络,则从缓存中获取。
实现缓存
1、开启缓存
这一步是设置缓存路径,以及缓存大小
<span style="font-size:14px;">File httpCacheDirectory = new File(context.getExternalCacheDir(), "responses");//设置缓存 10MCache cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024);client = new OkHttpClient.Builder().cache(cache).build();</span>2、设置 OkHttp 拦截器
两个操作都是在 Interceptor 中进行的
- 通过 CacheControl 控制缓存数据
CacheControl.Builder cacheBuilder = new CacheControl.Builder(); cacheBuilder.maxAge(0, TimeUnit.SECONDS);//多次访问一个接口,<span style="white-space:pre"></span>设置请求缓存时间,超过时间重新请求,否则去缓存 cacheBuilder.maxStale(365,TimeUnit.DAYS);//这个是控制缓存的过时时间 CacheControl cacheControl = cacheBuilder.build();
- 设置拦截器
Request request = chain.request();if(!StateUtils.isNetworkAvailable(MyApp.mContext)){ request = request.newBuilder() .cacheControl(cacheControl) .build();}Response originalResponse = chain.proceed(request);if (StateUtils.isNetworkAvailable(MyApp.mContext)) { int maxAge = 60; // read from cache return originalResponse.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public ,max-age=" + maxAge) .build();} else { int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale return originalResponse.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build();}
.maxAge(0,TimeUnit.SECONDS)设置的时间比拦截器长是不起效果
设置比拦截器设置的时间短就会以这个时间为主,我觉得是为了方便控制。
maxStale(365, TimeUnit.DAYS)设置的是过时时间,okthhp缓存分成了两个来考虑,一个是为了请求时直接拿缓存省流量,一个是为了下次进入应用时可以直接拿缓存。
直接上代码
private HttpControl(final Context context) { cookieStore = new PersistentCookieStore(context); CookieHandler cookieHandler = new CookieManager(cookieStore, CookiePolicy.ACCEPT_ALL); Interceptor interceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); /** * 未联网获取缓存数据 */ if (!CheckHasNet.isNetWorkOk(context)) { //在20秒缓存有效,此处测试用,实际根据需求设置具体缓存有效时间 CacheControl cacheControl = new CacheControl.Builder() .maxStale(30, TimeUnit.DAYS) .build(); request = request.newBuilder() .cacheControl(cacheControl) .build(); } return chain.proceed(request); } }; HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { Log.d("MyTAG", "OkHttp: " + message); } }); logging.setLevel(HttpLoggingInterceptor.Level.BODY); File httpCacheDirectory = new File(context.getExternalCacheDir(), "responses"); //设置缓存 10M Cache cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024); //1.创建Retrofit对象 client = new OkHttpClient.Builder().addInterceptor(logging) .addInterceptor(interceptor)//离线 .addNetworkInterceptor(provideCacheInterceptor())//在线 .cache(cache) .readTimeout(30000, TimeUnit.MILLISECONDS) .connectTimeout(30000, TimeUnit.MILLISECONDS) .cookieJar(new JavaNetCookieJar(cookieHandler)) .build(); retrofit = new Retrofit.Builder().client(client).baseUrl(Constant.BASEURL)// 定义访问的主机地址 .validateEagerly(true)// .addConverterFactory(GsonConverterFactory.create())//解析方法 Gson .addConverterFactory(JsonConverterFactory.create())//解析方法// .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); } public static Interceptor provideCacheInterceptor () { return new Interceptor() { @Override public Response intercept (Chain chain) throws IOException { Response response = chain.proceed( chain.request() ); // re-write response header to force use of cache // 正常访问同一请求接口(多次访问同一接口),给30秒缓存,超过时间重新发送请求,否则取缓存数据 CacheControl cacheControl = new CacheControl.Builder() .maxAge(3, TimeUnit.SECONDS ) .build(); return response.newBuilder() .header("Cache-Control", cacheControl.toString() ) .build(); } }; } public PersistentCookieStore getCookieStore() { return cookieStore; } /** * 单例模式 * * @return */ public static HttpControl getInstance(Context context) { if (instance == null) { synchronized (HttpControl.class) { if (instance == null) { instance = new HttpControl(context); } } } return instance; } public OkHttpClient getClient() { return client; } public void setClient(OkHttpClient client) { this.client = client; } public <T> T create(final Class<T> service) { return retrofit.create(service); }
注意
1、缓存是在每一次网络请求之后,重新保存的,所以在超过缓存过期时间后,Retrofit会在检查到没缓存之后自动请求网络服务器数据
2、缓存数据也是需要网络下载的,所以在网络不好的情况下,可能不能立即缓存
3、根据自身实际情况,制定缓存策略
0 0
- 【缓存策略】Retrofit+OkHttp实现缓存处理
- retrofit+okhttp 实现缓存
- Retrofit—okhttp Cache缓存策略
- Retrofit+okhttp 缓存的
- Android网络缓存,retrofit+okhttp
- Retrofit+OKHttp实现缓存以及遇到的问题
- okhttp或者retrofit实现网络缓存504错误原因
- 使用Retrofit和Okhttp实现网络缓存。无网读缓存,有网根据过期时间重新请求
- 使用Retrofit和Okhttp实现网络缓存。无网读缓存,有网根据过期时间重新请求
- Retrofit 源码解读之离线缓存策略的实现
- Retrofit 源码解读之离线缓存策略的实现
- Retrofit 源码解读之离线缓存策略的实现
- Android Retrofit RxJava实现缓存
- retrofit缓存
- Retrofit缓存
- OkHttp缓存
- OKhttp缓存
- okhttp缓存
- Vufoia——动态添加、删除识别数据集
- Android中visibility属性VISIBLE、INVISIBLE、GONE的区别
- iOS之PJSIP的编译与简单使用
- JDK并发数据结构
- 详解android中AsyncTask的使用
- 【缓存策略】Retrofit+OkHttp实现缓存处理
- ORACLE_HOME目录满了 导致的ORA-01114 ORA-29701的问题
- nginx 已有80端口服务如何在开启一个非80端口的静态资源指向
- phpmyadmin里root无法登陆的临时解决办法
- laravel 学习网站
- JAVA增删改查 代码范例
- MacBook怎样装Win10 双系统玩转Win10
- leetcode-409. Longest Palindrome 最长回文串的长度
- 重学Activity,由浅入深。