Android WebView中shouldOverrideUrlLoading方法的一些坑

  最近因为公司业务,需要跟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 return true. 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 return false, without calling [WebView.loadUrl(String)](https://developer.android.com/reference/android/webkit/WebView.html#loadUrl(java.lang.String)).

Android WebView中shouldOverrideUrlLoading方法的一些坑_第1张图片

尼玛!这TM是个标准的错误写法啊!

于是...我毫不犹豫的把这两行代码改掉了,如下:

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    //view.loadUrl(url);
    //return true;
    return false;
}
Android WebView中shouldOverrideUrlLoading方法的一些坑_第2张图片

然而,万万没想到...

第二天测试小姐姐就报bug了:哥!网页加载不出来了,一直loading!

Android WebView中shouldOverrideUrlLoading方法的一些坑_第3张图片

没办法,查吧,回退上一个版本是好用的,总共也没几个改动的地方。虽然我笃定这里不会出问题,但奈何其他地方也都没问题。最后一个改动一个改动验证,发现就是这里出了问题。

淦!!!

为毛???

Android WebView中shouldOverrideUrlLoading方法的一些坑_第4张图片

没办法,复现,查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就一直不消失了。

这里需要吐槽一下这个变量命名,太尼玛让人误解了,完全不知道干啥的,所以之前都选择性忽略了它。


Android WebView中shouldOverrideUrlLoading方法的一些坑_第5张图片

后来做了一系列实验,结果大概是下面这样的:

虽然官方文档建议不拦截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的准确性

补充: 如果是点击页面,触发标签,则对应的回调顺序如下:

                       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问题也很快搞定了。

只能说,有得必有失吧,多踩坑,也不见得是坏事~~~

你可能感兴趣的:(Android WebView中shouldOverrideUrlLoading方法的一些坑)