美文网首页AndroidAndroidAndroid知识进阶
Android WebView中shouldOverrideUr

Android WebView中shouldOverrideUr

作者: qiuqifan | 来源:发表于2018-09-02 18:06 被阅读7878次

      最近因为公司业务,需要跟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)).

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

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

    相关文章

      网友评论

        本文标题:Android WebView中shouldOverrideUr

        本文链接:https://www.haomeiwen.com/subject/djvmwftx.html