Retrofit2.0+Okhttp不依赖服务端的数据缓存

原创 2016年09月18日 19:45:23

随着Retrofit在项目中的使用,替换的以前使用的网络框架,相关的缓存机制也要进行替换,网络上大部分的Retrofit+okhttp缓存资料都是进行针对所有url的而且需要服务端的配合。有些时候是先有服务然后app去调用这些服务,所以这个时候没有服务端的配合我们在前端实现缓存比较空难但并不是很可以。(举个列子,有一个原来的服务更本不支持cache,但是我们在app中需要缓存这个服务的数据,这应该是前一段时间替换网络库时最后遇到的问题)。

为什么要做缓存处理?

客观回答:

减少服务器负荷,降低延迟提升用户体验。复杂的缓存策略会根据用户当前的网络情况采取不同的缓存策略,比如在2g网络很差的情况下,提高缓存使用的时间;不用的应用、业务需求、接口所需要的缓存策略也会不一样,有的要保证数据的实时性,所以不能有缓存,有的你可以缓存5分钟,等等。

自己回答:

在绝大部分的项目中我们前端开发人员只是考虑用户的流量,用户在产品性能上的体验。所以有时候服务端和前端没有依赖,即服务不支持缓存那么前端又需要缓存那么我们应该怎么做?普通的缓存模式已经很难适应这种需求了,下面将的就是利用Retrofit2.0+OkHttp3.0的缓存原理去实现我们的需求。

Retrofit+OkHttp的缓存机制:

  • 在 data/data/<包名>/cache 下建立一个用来进行数据存储的文件夹,保持缓存数据。
  • 这样我们就可以在请求的时候,根据业务逻辑,请求网络数据或者读取缓存的数据。

缓存使用情况:

  • 一般情况下无网络,数据从缓存中读取;
  • 有网络则根据请求头,判断是请求网络还是读取缓存。

说到缓存,不是很了解的Http缓存的同学亦可以看一下浏览器 HTTP 协议缓存机制详解 这篇文章讲的很详细。

Cache控制:

该部分对理解怎么缓存很重要~!

1、用在request中的cache控制头

Pragma: no-cache :兼容早起HTTP协议版本 如1.0+
Cache-Control: no-cache ,表示不希望得到一个缓存内容。只是希望,cache设备可能忽略。
Cache-Control: no-store,表示client与server之间的设备不能缓存响应内容,并应该删除已有缓存。
Cache-Control: only-if-cached,表示只接受是被缓存的内容

2、用在response中控制cache的头

Cache-Control: max-age=3600,用相对于接收到的时间开始可缓存多久
Cache-Control: s-maxage=3600,与上面类似,只是s-maxage一般用在cache服务器上,并只对public缓存有效
Expires: Fri, 05 Jul 2002, 05:00:00 GMT基于GMT的时间,绝对时间,但该头容易受到本地错误时间影响
Cache-Control: must-revalidate 该头表示内容可以被缓存但每次必须询问是否有更新。

HTTP-请求、响应、缓存

代码实现:

看到这里应该对缓存有一定的了解了,那么现在来看看怎么利用Retrofit2.0+Okhttp缓存的实现。

创建缓存文件,并对okhttp进行设置

public class RetrofitApiFactory{
    private static OkHttpClient okHttpClient = null ;
    private static File cacheFile = new File(ImageUtils.getAppCacheDir(), "xxxCache");
    private static Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
    /******中间代码省略*****/
    public static void initOkHttpClient(){
        okHttpClient =
                new OkHttpClient.Builder()
                        .cache(cache)
                        .readTimeout(TIME_OUT, TimeUnit.SECONDS)
                        .writeTimeout(TIME_OUT, TimeUnit.SECONDS)
                        .addInterceptor(new JobInterceptor("Interceptor"))  
                        //only 有网情况下,一分钟内每次请求都会重新请求,不会走缓存
                        .addNetworkInterceptor(new JobInterceptor("NetworkInterceptor"))    
                        //only 如果超过1分钟,离线请求不成功
                        .build();
        clearCacheMap() ;
    }
}

控制Cache中最最最主要的部分:

public class JobInterceptor implements Interceptor {
    /******中间代码省略*****/
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request() ;
        if (!TextUtils.isEmpty(getCookie())) {
            if (!NetworkDetection.getIsConnected()) {
                try {
                    request = request
                            .newBuilder()
                            .addHeader("Cookie", getCookie())
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                try {
                    request = request
                            .newBuilder()
                            .addHeader("Cookie", getCookie())
                            .build();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        Response response = null;
        try {
            response = chain.proceed(request);
            if(!response.isSuccessful()){
                RetrofitApiFactory.initOkHttpClient();
            } else {//如果请求体有缓存数据的需要那么对响应体进行缓存
                int maxAge = request.cacheControl().maxAgeSeconds();
                if (request.cacheControl().isPublic() && maxAge > 1) {
                    response = response.newBuilder()
                            .removeHeader("Pragma")//清楚响应体对Cache有影响的信息
                            .removeHeader("Cache-Control")//清楚响应体对Cache有影响的信息
                            .header("Cache-Control", "public, max-age=" + maxAge)
                            .build();
                }
            }
        } catch (IOException e) {
            RetrofitApiFactory.initOkHttpClient();
            throw new IOException(e) ;
        }

        return response;
    }
}

接口使用:

@Headers("Cache-Control: public, max-age=86400")
@GET
Call<ResponseBody> getCacheData(@Url String url);

解析:

上面的绝大部分内容大家都在类似的文章上看到的。这里主要讲一下几点:

一、我们所用的接口服务不支持缓存,所以我不能只修改头信息而让服务端返回的response响应体去实现数据本地缓存。当然在没有网络的情况下我们可以尝试去读取缓存。

二、因为服务端没有提供response响应体的缓存,所以我们清除response响应体的Pragma、Cache-Control信息,然后根据自己设定的request请求体中的Cache信息去修改response响应体的Cache信息从而达到数据可以缓存。

三、在开发的过程中遇到如果一个接口在某次请求返回404,那么以后的结果总是请求失败的404页面。所以在请求失败的时候需要初始化OkHttpClient实例。

如有问题,欢迎沟通指正~!~!
参考文章Retrofit-Cache

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

retrofit2.0缓存设置

前言 – 在 Android 开发过程中,Retrofit 的出现绝对是里程碑式的,说起 Retrofit 不得不说 square,这绝对是家l好公司,业界良心。 回到今天的主题...

Retrofit2.0+okhttp3设置缓存

1.首先需要一个工具方法:判断当前网络状态 方法:/** * 判断网络是否可用 * * @param context Context对象 ...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

Retrofit2.0+okhttp3缓存机制以及遇到的问题

简介retrofit本身并没有缓存。如果想缓存,它要么必须让retrofit之上的应用层知道你的域和如何缓存事物,或它需要在retrofit之下HTTP client层知道HTTP的语义。OkHttp...

Retrofit2.0+Okhttp不依赖服务端的数据缓存

随着Retrofit在项目中的使用,替换的以前使用的网络框架,相关的缓存机制也要进行替换,网络上大部分的Retrofit+okhttp缓存资料都是进行针对所有url的而且需要服务端的配合。有些时候是先...

sqlCachedependency【数据缓存依赖】 的使用

【新手】文章  为提高页面性能,对数据进行缓存是个不错的办法,但我们以前在页头加上,这个确实对数据进行缓存了,但不能及时更新,要等到设置的时间失效才会显示最新的数据,我想这样的话索性不用它。但为了性能...

缓存依赖、数据库缓存依赖学习以及在LinQ当中使用缓存依赖

导读: ◆缘起 ◆缓存简述 ◆缓存依赖简述 ◆自定义缓存依赖分析 ◆数据库缓存依赖学习 ◆LINQ缓存依赖实现 ◆文档更新说明 ◆附:缓存依赖研究项目源码(包括数据库) ◆参考资...
  • xpnew
  • xpnew
  • 2012-05-03 16:47
  • 564

Retrofit2.0和Okhttp进行的缓存

原文:http://blog.csdn.net/picasso_l/article/details/50579884 简介 retrofit本身并没有缓存。 如果想缓存,它要么必须让retrofit...

缓存依赖、数据库缓存依赖学习以及在LinQ当中使用缓存依赖

导读: ◆缘起 ◆缓存简述 ◆缓存依赖简述 ◆自定义缓存依赖分析 ◆数据库缓存依赖学习 ◆LINQ缓存依赖实现 ◆文档更新说明 ◆附:缓存依赖研究项目源码(包括数据库) ◆参考资料 ...

SQL数据缓存依赖总结

以前只听过SQL server数据缓存依赖,但一直没使用,由于项目需要,才研究了一番,发现了一个很诡异的问题,竟然是一个操作顺序问题导致的。   SQL server数据缓存依赖有两种实现模式,轮询...

Sql缓存依赖

Sql缓存依赖主要分为两种: 1.轮询模式(poll model) 2.推模式(push model) 今天先讲解第一种模式:轮询 要使用sql轮询模式,得做三方面的工作: 1.对数据库启用...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)