shouldOverrideUrlLoading返回值的处理及webview重定向造成无法返回的解决

文章目录

  • 一、shouldOverrideUrlLoading返回值理解
  • 二、shouldOverrideUrlLoading不同返回值的使用场景
    • 1.若没有设置 WebViewClient
    • 2.若设置WebViewClient 且该方法返回 true
    • 3.若设置WebViewClient 且该方法返回 false
    • 4.loadurl
  • 三、webView页面返回处理
    • 1.正常情况下
    • 2.页面重定向情况下

一、shouldOverrideUrlLoading返回值理解

网上给出的解释良莠不齐,还是只有自己来研究才放心。首先,有必要在此澄清一下shouldOverrideUrlLoading返回值的正确理解:

WebView#shouldOverrideUrlLoading 的 api doc 如下

public boolean shouldOverrideUrlLoading (WebView view, String url)
Added in API level 1

Give the host application a chance to take over the control when a> new url is about to be loaded in the current WebView.
If WebViewClient is not provided, by default WebView will ask Activity Manager to choose the proper handler for the url. 
If WebViewClient is provided,return true means the host application handles the url, while return false means the current
WebView handles the url. This method is not called for requests using the POST "method".

Parameters
view  The WebView that is initiating the callback.
url   The url to be loaded.

Returns
True if the host application wants to leave the current WebView and handle the url itself, otherwise return false.

翻译一下,三种情况:

若没有设置 WebViewClient 则在点击链接之后由系统处理该 url,通常是使用浏览器打开或弹出浏览器选择对话框。
若设置WebViewClient 且该方法返回 true ,则说明由应用的代码处理该 url,WebView 不处理。
若设置WebViewClient 且该方法返回 false,则说明由 WebView 处理该 url,即用 WebView 加载该 url。

二、shouldOverrideUrlLoading不同返回值的使用场景

接上文,还是分三种情况:

1.若没有设置 WebViewClient

这种很清晰,字面理解就行了,就是在mWebView.setWebViewClient(new WebViewClient())这句代码不写的情况下加载url时会由系统来指定浏览器打开,如果手机安装了多个浏览器的话会弹出对话框让用户来选择使用哪个浏览器打开。总之也就是不会使用我们自己程序内的webview容器来加载了。

2.若设置WebViewClient 且该方法返回 true

设置 WebViewClient 且在其 shouldOverrideUrlLoading 方法返回 true,则系统不会继续处理,处理由开发者接管,例如:

			 @Override
              public boolean shouldOverrideUrlLoading(WebView webView, String url) {
                  return true;
              }

如上,处理方式由自己来指定,如果不指定则不会跳转,不会响应.

3.若设置WebViewClient 且该方法返回 false

			 @Override
             public boolean shouldOverrideUrlLoading(WebView webView, String url) {
                 return false;
             }

这种情况下就会使用我们自己的webview来打开url.

4.loadurl

			@Override
            public boolean shouldOverrideUrlLoading(WebView webView, String url) {
            	 webView.loadUrl(url);
                 return false/true;
             }

若设置WebViewClient且在方法中调用loadUrl的话则不会走retrun,所以返回true和false都是无效的,会重新加载url。

三、webView页面返回处理

1.正常情况下

正常情况下在webView所在Activity中重写onBackPressed,屏蔽原生的super.onBackPressed使用mWebView.goBack()返回前一个页面即可,如下:

   @Override
public void onBackPressed() {
	//super.onBackPressed();
    if(mWebView!=null && mWebView.canGoBack()){
        mWebView.goBack();
    }else {
        finish();
    }
}

首页再返回才退出activity。

2.页面重定向情况下

1.使用HitTestResult 判断是否发生重定向,过滤重定向的url不入返回栈。

   @Override
    public void onBackPressed() {
        pageGoBack(mWebView,mWebViewClient);
    }

    public boolean pageGoBack(WebView web, MyWebViewClient client) {
        if(client == null || web == null){
            return false;
        }
        final String url = client.popLastPageUrl();
        if (url != null) {
            web.loadUrl(url);
            return true;
        }
        finish();
        return false;
    }

    class MyWebViewClient extends WebViewClient {
        /**
         * 返回栈
         */
        private final Stack mUrls = new Stack<>();
        /**
         * 记录操作路径的url临时栈
         */
        private List mTempUrls = new ArrayList<>();
        /**
         * 判断页面是否加载完成
         */
        private boolean mIsLoading;
        private String mShowingUrl;
        private String mUrlBeforeRedirect;

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            Log.e("onPageStarted","url:"+url);
            recordUrl(url);
            //this.mIsLoading = true;
        }

        /**
         * 记录非重定向链接, 避免刷新页面造成的重复入栈
         *
         * @param url 链接
         */
        private void recordUrl(String url) {
            //这里还可以根据自身业务来屏蔽一些链接被放入URL栈
            mShowingUrl = url;

            if (!TextUtils.isEmpty(url) && !url.equalsIgnoreCase(getLastPageUrl())) {
                if (!(url.startsWith("http") || url.startsWith("https"))) {
                    return;
                }
                if(!TextUtils.isEmpty(mUrlBeforeRedirect)&&mUrlBeforeRedirect.equals(url)){//重定向的url屏蔽
                    mUrlBeforeRedirect = null;
                    return;
                }

                mUrls.push(url);
            }
        }

        /**
         * 获取上一页的链接
         **/
        private synchronized String getLastPageUrl() {
            return mUrls.size() > 0 ? mUrls.peek() : null;
        }

        /**
         * 推出上一页链接
         */
        public String popLastPageUrl() {
            if (mUrls.size() >= 2) {
                mUrls.pop(); //当前url
                return mUrls.pop();
            }
            return null;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            view.getSettings().setBlockNetworkImage(false);
            Log.e("onPageFinished","url:"+url);

        }

        @Override
        public void onReceivedSslError(WebView webView, SslErrorHandler sslErrorHandler,
                SslError sslError) {
            //super.onReceivedSslError(webView, sslErrorHandler, sslError);
            sslErrorHandler.proceed();// 接受所有网站的证书
        }

        @SuppressLint("LongLogTag")
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            Log.e("shouldUrlLoading","url:"+url);

            if (url.startsWith("tel:")) {
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                startActivity(intent);
                return true;
            } else {
                if (!(url.startsWith("http") || url.startsWith("https"))) {
                    return true;
                }
                WebView.HitTestResult hitTestResult = view.getHitTestResult();
                int hitType = hitTestResult.getType();
                if (hitType != WebView.HitTestResult.UNKNOWN_TYPE) {
                    Log.e("WebViewManger","没有进行重定向操作");
                    //这里执行自定义的操作
                    view.loadUrl(url);
                    return true;
                } else{
                    Log.e("WebViewManger","进行了重定向操作");
                    mUrlBeforeRedirect = url;
                    //重定向时hitType为0 ,执行默认的操作
                    return false;
                }

            }
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.title_back: {
                pageGoBack(mWebView,mWebViewClient);
                break;
            }
        }
    }

shouldOverrideUrlLoading返回值的处理及webview重定向造成无法返回的解决_第1张图片

你可能感兴趣的:(android基础总结)