版权声明:web
本帐号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影全部。浏览器
未经容许,不得转载。缓存
在 Android 开发中,若是用过 WebView 来加载一个网页,老是逃不过 WebView 的缓存策略的设定。WebView 自己也提供了多种缓存的策略来供开发者使用,而有一些涉及到 Http 协议,因此将两个概念集中整理一块儿讲解,但愿对你们有帮助。服务器
WebView 自己是提供了设置缓存策略的 API 的,可使用 WebSetting 对象进行设置。网络
而 WebSetting 中,能够设置多种缓存策略,以下:post
LOAD_CACHE_ONLY 和 LOAD_NO_CACHE 都是比较极端的状况,通常咱们也不会使用。LOAD_NORMAL 已经被废弃了,也没什么好说的,而 LOAD_CACHE_ELSE_NETWORK 自己已经决定了策略,只要本地有,就不会从新获取,也不会有什么能够变化的。测试
LOAD_DEFAULT 才是咱们项目上比较经常使用测策略,本文主要对 LOAD_DEFAULT 模式进行讲解,自己它也是 WebView 的默认模式。可是实际开发中,最好仍是显式设定一下,不少 ROM 均可能会修改这部分代码的,我在乐视手机上作过测试,它的默认策略就是 LOAD_CACHE_ELSE_NETWORK 。3d
先来看看 LOAD_DEFAULT 的 API。code
能够看到,它是默认策略,若是不设定强制策略,在资源没有过时的时候,从缓存获取,若是资源过时了,则从网络获取。cdn
这样的一个策略,就和 Http 缓存相关了,由协议来肯定资源加载的策略。
既然知道 WebView 也是遵循 Http 的缓存策略的,那么咱们就先来看看 Http 缓存的策略是怎么样的。
用 Charles 抓一个包,看看一个常规的静态文件。
能够看到,一个请求的响应头中,包含了不少信息,而其中有一部分是和缓存相关的,下面咱们来一一讲解。
Cache-Control 是 Http 1.1 中新增长的一个用来定义缓存时间的头。若是使用了 Cache-Control 的话,会覆盖掉 Http 1.0 中的一些,例如:Pragma、Expires等,以 Cache-Control 为准。
Cache-Control 也是一个通用的 Http 报文头字段,它能够分别在请求报文和响应报文中使用,而它做为不一样的使用方式,存在不一样的含义。
Cache-Control 的规范写法:
Cache-Control:cache-directive
cache-directive 的可选值有不少,no-cache、no-store、only-if-cached 等,有兴趣的能够自行查查 Http 协议中的定义。可是通常而言,如上图所示,会使用 max-age 来设定一个最大的有效时间的方式来使用,max-age 设定的时间,单位为秒(s)。
Cache-Control 的 max-age 出如今请求报文头和响应报文头中,含义是不同的。
WebView 中,若是被设定为 LOAD_DEFAULT 的话,是遵循此规则的,也就是说,当请求资源回来以后,会根据 max-age 设定当前资源的过时时间,在这个时间范围内,则不会从新请求,会直接从缓存中读取资源,而上面的例子中,max-age 被设定为 40000,差很少 11 个多小时。
Cache-Control 这个报文头,决定了客户端是否须要向服务器发送请求。可是,若是已通过期(超过 max-age 设定的时间),当这个请求发送到服务器以后,是否须要服务器返回一个完整的数据呢?
虽然咱们设定了 max-age ,可是它只能表示一个合理的变化频度,也就是说,可能超过这个 max-age 设定的时间,可是请求的文件也并无变化。那么服务器只须要告知客户端,文件没变化,你仍是读缓存的资源就行了。
这个策略,就是使用 ETag 和 Last-Modified 来校验的。当客户端经过 max-age 判断发现请求的资源文件已经再也不新鲜了,须要从服务器上从新获取,在向服务器发送请求的时候,就会经过这些值告知服务器本地缓存资源的一个标识,服务器就经过这个标识来判断客户端缓存的资源是否依然新鲜。
能够看到,当 max-age 失效以后,发送的请求,会携带 if-None-Match 和 if-Modified-Since 这两个报文头,服务器就是根据这两个报文头来断定客户端的资源是否过时,若是过时,则返回新的资源,若是未过时,则返回一个状态码304的一个响应,告知客户端能够继续读取缓存使用。
细心的应该能够看到,请求头里的 if-None-Match 就是以前响应头里的 ETag ,而 if-Modified-Since 就是以前响应头里的 Last-Modified。
下面看看他们的含义:
固然,对于请求头,还有其余的规则,例如:if-Match、if-Unmodified-Since 等,这个就看服务器的和客户端的实现了。
这里的 ETag 和 Last-Modified 其实能够分开使用,可是若是被同时使用,则要求服务器对这两个值都进行校验,都校验经过了才会返回 304。
那么这么作,有什么好处,实际是全部的缓存策略,都是为了减少各类地方的压力。对于客户端而言,减小了网络请求的压力,对于服务器而言,也减少了请求和流量的压力。
能够看到,一个完整的资源请求,须要 24kb,而当资源没有过时的时候,只须要 1kb 左右便可,而且响应的时间也更快了。
到这里,对于 WebView 的各个缓存策略的理解应该就明确了。若是使用 LOAD_DEFAULT 则依赖 Http 的缓存策略,而Http 缓存又是依赖 Cache-Control、ETag、Last-Modified 等值来肯定的。
那么,若是咱们将 CacheMode 设定为 LOAD_DEFAULT ,而且给出了一个 max-age = 40000 资源响应头,在不清理缓存的状况下,咱们的 WebView 就不会对该继续发送请求?这样咱们不当心设定了一个极大的 max-age 值,是否客户端的资源好久才会被更新?
其实并非绝对的,在 WebView 中,加载网页,咱们通常使用 loadUrl() 方法,当使用 loadUrl() 方法的时候,它会彻底遵循上面给出的缓存策略,在没有过时的时候去从缓存中读取资源。
可是浏览器在 Http 缓存策略以外,还提供了强制刷新的策略,这样也保证了在某些状况下,能够去服务器是从新获取资源。而这个策略反应在 WebView 中,就是使用 reload() 方法。当使用 reload() 方法的时候,WebView 会从新请求资源,并在报文头中,修改 max-age 为 0 。这样既能够保证当前刷新了会有一个真实的网络请求,又能保证在缓存资源不过时的状况下,不给服务器形成压力。
Http 的缓存策略,在 Android 开发中,并非只用在 WebView 上,一些网络库,例如 OkHttp,也是依赖 Http 缓存策略来进行缓存数据的。
本文参加掘金技术征文:juejin.im/post/58d8e9…