问题描述
最近在和公司其他项目组沟通联调H5的时候,意外发现对方发过来的地址可以加载,但是没有办法正常刷新。
尤其是对方服务器上已经重新部署页面,二次进入的情况下,依旧显示上一次加载过的内容,直到应用重启为止。
问题复现
写个 WebView 的 demo,然后在 WebViewClient 的所有方法加上日志来监控网页的运行情况。
此处假定测试网址为 https://www.mobibrw.com/#/?p=43064
对网页第一次加载可以正常加载(即调用了 onPageStarted 和 onPagefinished )。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
I/MyWebView: shouldInterceptRequest: https://www.mobibrw.com/#/?p=43064 I/MyWebView: onProgressChanged: 10 I/MyWebView: shouldOverrideUrlLoading: url:https://www.mobibrw.com/#/?p=43064 I/MyWebView: onPageStarted: url:https://www.mobibrw.com/#/?p=43064, favicon :null ............省略中间无关日志......... I/MyWebView: onPageFinished: url:https://www.mobibrw.com/#/?p=43064 I/MyWebView: onProgressChanged: 70 I/MyWebView: onProgressChanged: 100 |
第二次调用 loadUrl() 加载的时候只会刷新图标,不会真的重新加载网页(只调用了 onPageFinished )。
1 2 3 4 5 6 7 |
I/MyWebView: onProgressChanged: 10 I/MyWebView: doUpdateVisitedHistory: url:https://www.mobibrw.com/#/?p=43064, isReload:false I/MyWebView: onPageFinished: url:https://www.mobibrw.com/#/?p=43064 I/MyWebView: onProgressChanged: 100 |
最后发现当我们第二次加载链接的时候,如果调用的是 webview.loadUrl(url) ,就无法刷新。
但是如果调用的是 webview.reload(url) ,就可以正常刷新网页。
调用 reload 时日志如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
I/MyWebView: onProgressChanged: 10 I/MyWebView: shouldInterceptRequest: url:https://www.mobibrw.com/#/?p=43064 I/MyWebView: shouldOverrideUrlLoading: url:https://www.mobibrw.com/#/?p=43064 I/MyWebView: onPageStarted: url:https://www.mobibrw.com/#/?p=43064, favicon :android.graphics.Bitmap@a1689fc I/MyWebView: onProgressChanged: 23 ............省略中间无关日志......... I/MyWebView: onProgressChanged: 100 I/MyWebView: onPageFinished: url:https://www.mobibrw.com/#/?p=43064 |
原因分析
知道了调用 reload 可以重刷网页,调用 loadUrl 无法重刷网页,问题就在于这两个方法的差别了。
经过查找,得知了真正原因是因为对方的 URL 带了 #,所以导致 loadUrl 不会刷新网页。
将网址改为 https://www.mobibrw.com/?p=43064,再次调用 loadUrl,第二次加载日志如下:
1 2 3 4 5 6 7 8 9 10 11 |
I/MyWebView: shouldInterceptRequest: url:https://www.mobibrw.com/?p=43064 I/MyWebView: onProgressChanged: 10 I/MyWebView: onPageStarted: url:https://www.mobibrw.com/?p=43064, favicon :android.graphics.Bitmap@1d36963 I/MyWebView: onProgressChanged: 70 I/MyWebView: onProgressChanged: 100 I/MyWebView: onPageFinished: url:https://www.mobibrw.com/?p=43064 |
可以看到有正常执行 onPageStarted 和 onPageFinished 。
那么为什么 URL 里面带了个 #,我们的 WebView 就无法通过 loadUrl 刷新网页了呢?
简单来说,URL 中 # 以及其后面的部分,是客户端这边的位置定位符,在加载网页的时候并不会真正的发送给服务端。
我们的测试网址由于带有 #,所以无论怎么调用 loadUrl,他都判断我们只是改变了网页内部的相对位置(虽然实际上我们并没有改变),不会重新加载这个网页,只是加载网页图标。
那为什么 webview.reload 又可以重刷网页呢,实际上是因为 loadUrl 默认会有缓存策略,而 reload 是无视缓存策略强制刷新的,所以我们拿这个地址去浏览器运行,是可以正常刷新的。
结论
loadUrl 会有缓存策略,二次加载遇到带 # 的网页不会刷新,reload 无视缓存策略会强制刷新。