天天看點

shouldOverrideUrlLoading傳回值的處理及webview重定向造成無法傳回的解決一、shouldOverrideUrlLoading傳回值了解二、shouldOverrideUrlLoading不同傳回值的使用場景三、webView頁面傳回處理

shouldOverrideUrlLoading傳回值的處理及webview重定向造成無法傳回的解決一、shouldOverrideUrlLoading傳回值了解二、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<String> mUrls = new Stack<>();
        /**
         * 記錄操作路徑的url臨時棧
         */
        private List<String> 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重定向造成無法傳回的解決一、shouldOverrideUrlLoading傳回值了解二、shouldOverrideUrlLoading不同傳回值的使用場景三、webView頁面傳回處理