5月 192016
 

我们在页面(该页面仅仅用于重定向操作)发起某个请求、请求正常,但按下物理返回键返回上个页面时遇到这个问题,搜了很多帖子,有的情况说这是因为web站点的页面设置的缓存策略是无缓存,即http header中有如下字段:Cache-Control: no-store,如下:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Encoding: gzip


此时由于页面没缓存、webview去找缓存却没找到,此种情况下,需要看web站点中“no-store”字段是否有必要,没啥作用的话可以尝试去掉“no-cache”试试看,参见这个帖子。另外还有一种改法,是直接修改webview控件,如下。

if (Build.VERSION.SDK_INT >= 19) {
 mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
}

但修改webview控件的方式其实有很大的风险,因为webview本身有多种缓存策略,如下:

LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
LOAD_DEFAULT: 根据cache-control决定是否从网络上取数据。
LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

默认的策略是根据页面中的cache-control字段来判断是读取缓存还是去网上取最新页面。如果改成LOAD_CACHE_ELSE_NETWORK,而业务上需要每次都从web站点取最新数据,那将发生错误(因为webview将优先从本地缓存中取)。
我遇到这个问题时,一开始以为是页面缓存设置问题,但跟服务端同事调试后发现,并不是由Cache-Control: no-store 引起的,又继续查,才发现这样一个问题:我们所采用的框架中,webview在load一个页面时,会先判断是否为post请求,若是则调用postUrl方法,否则就调用loadUrl方法(loadUrl是用GET方式发请求哦!!)。出问题的页面发起的请求是post请求,而按下android物理返回键时webview会调用loadUrl重新发请求,这就导致本来应该发POST请求去load上个页面、结果却发了GET请求,这才导致报错。stackoverflow上也有提到类似的情况,见此链接
为解决这个问题,我们采用了在web站点上用js控制页面重定向,具体方式跟我们的实现有关,贴出来意义不大,在此略去。顺带说句,webview中注册js函数很费劲,我们调了好几天,最终选定了jsbridge,有兴趣的童鞋自己查吧。


 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)