最近因为公司业务,需要跟WebView打交道。
等我查过网上资料与官方文档,了解了shouldOverrideUrlLoading方法以后,在代码里面看到了如下代码:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
错误说法4:这是一种广为流传的用法,在shouldOverrideUrlLoading中
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
便可以在WebView中加载该url。
对于说法4,直接返回false即可达到同样的效果。
Note: Do not call
[WebView.loadUrl(String)](https://developer.android.com/reference/android/webkit/WebView.html#loadUrl(java.lang.String))
with the same URL and then returntrue
. This unnecessarily cancels the current load and starts a new load with the same URL. The correct way to continue loading a given URL is to simply returnfalse
, without calling[WebView.loadUrl(String)](https://developer.android.com/reference/android/webkit/WebView.html#loadUrl(java.lang.String))
.
尼玛!这TM是个标准的错误写法啊!
于是...我毫不犹豫的把这两行代码改掉了,如下:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//view.loadUrl(url);
//return true;
return false;
}
然而,万万没想到...
第二天测试小姐姐就报bug了:哥!网页加载不出来了,一直loading!
没办法,查吧,回退上一个版本是好用的,总共也没几个改动的地方。虽然我笃定这里不会出问题,但奈何其他地方也都没问题。最后一个改动一个改动验证,发现就是这里出了问题。
淦!!!
为毛???
没办法,复现,查log吧...
一通操作之后,发现出问题的时候,加载的url是"http://www.taobao.com",看Log,有重定向到"https://www.taobao.com"。这是很多网站通用的做法。
没毛病啊??? return false也没问题啊? 为什么就加载不了了呢?
等等??? 这是个啥??
一行一行过代码的时候,突然有个神秘的mShouldOverrideUrlLoading变量引起了我的注意。大概是下面这样的。
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
mShouldOverrideUrlLoading = true;
//view.loadUrl(url);
//return true;
return false;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
mShouldOverrideUrlLoading = false;
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (mShouldOverrideUrlLoading) {
return;
}
//回调加载成功的函数
}
那这个变量是干嘛的???
参考这篇博客,通过这个flag来判断是否有重定向逻辑,保证重定向时Loading界面不消失。
再一看Log,果然!
如果return false,onPageFinished虽然也会被回调,但是mShouldOverrideUrlLoading变量这个时候的值是true,所以没有执行加载成功的回调,loading就一直不消失了。
这里需要吐槽一下这个变量命名,太尼玛让人误解了,完全不知道干啥的,所以之前都选择性忽略了它。
后来做了一系列实验,结果大概是下面这样的:
虽然官方文档建议不拦截url时返回false,但这种情况下(希望重定向时继续显示loading进度条)必须使用view.loadUrl(url);加return true;
原因:在这里通过view.loadUrl方法,虽然跟return false的效果一样,
但是可以保证非重定向的url不会回调shouldOverrideUrlLoading方法,
从而可以通过mIsRedirect这个flag来过滤重定向链接。
比如目标url是http://www.taobao.com, 会重定向到https://www.taobao.com。
如果返回false,则回调执行顺序如下:
onPageStarted(http://www.taobao.com) -> onPageStarted(https://www.taobao.com) -> shouldOverrideUrlLoading(https://www.taobao.com) -> onPageFinished(https://www.taobao.com)
如果改成view.loadUrl(url);加return true; 则回调执行顺序如下:
onPageStarted(http://www.taobao.com) -> onPageStarted(https://www.taobao.com) -> shouldOverrideUrlLoading(https://www.taobao.com) -> onPageFinished(https://www.taobao.com) -> onPageStarted(https://www.taobao.com) -> onPageFinished(https://www.taobao.com)
可以看到返回false的话,onPageFinished会少执行一次,这样无法保证标识重定向flag的准确性
补充: 如果是点击页面,触发<link>标签,则对应的回调顺序如下:
shouldOverrideUrlLoading(https://www.taobao.com) -> onPageStarted(https://www.taobao.com) -> onPageFinished(https://www.taobao.com)
这种情况下,判断条件仍然满足,Loading界面也会消失。
所以,答应我,当你在做一个webview全局loading进度条,需要过滤重定向请求的时候,记得不要return false,具体写法可以参照下面代码:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
mIsRedirect = true;
view.loadUrl(url);
return true;
//return false;// !!!错误做法
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
mIsRedirect = false;
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (mIsRedirect) {
return;
}
//回调加载成功的函数
}
}
当当当,这篇文章到这就结束了!
虽说因为这个坑花费了不少时间,但是也因为这个对webview了解深了很多,解决完这个问题以后,另外一个比较纠结的webview问题也很快搞定了。
只能说,有得必有失吧,多踩坑,也不见得是坏事~~~