WebView之WebViewClient詳解

一、與WebChromeClient的區別
1.WebChromeClient主要輔助WebView處理JavaScript的對話框、網站圖標、網站title、加載進度等比如

onProgressChanged//加載進度,可以在這裏實現頂部進度條
onJsAlert //WebView上alert無效,需要定製WebChromeClient處理彈出,設置webView.setWebChromeClient(new WebChromeClient());即可
onJsPrompt
onJsConfirm

2、WebViewClient主要幫助WebView處理各種通知、請求事件的,比如:

shouldOverrideUrlLoading//WebView中打開新鏈接時調用,下面詳解
onLoadResource
onPageStart
onPageFinish
onReceiveError

二、主要API

1、shouldOverrideUrlLoading(WebView view, String url)

  /**
     * 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".
     *
     * 該方法主要是爲了判斷新網頁的打開方式,當一個新的請求地址在頁面發起時,如果沒有設置WebViewClient系統默認返回false,即調用系統自帶瀏覽器打開。
     * 如果設置了WebViewClient,默認返回false,當返回true時應用自行處理,不調用系統瀏覽器,並需開發者自行調用 view.loadUrl(url);
     * 對於使用POST“方法”的請求,不調用此方法
     * 
     * @param view 當前WebView
     * @param url 加載的url
     * @return True if the host application wants to leave the current WebView
     *         and handle the url itself, otherwise return false.
     * @deprecated Use {@link #shouldOverrideUrlLoading(WebView, WebResourceRequest)
     *             shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead.
     */
    @Deprecated
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        return false;
    }

當我們需要當前應用自行處理,不調用系統瀏覽器的時候,應該重寫該方法,讓其返回true。**需要注意的是:**WebView只能識別”http://”和”https://”開頭的協議,如果是我們自定義的協議,比如:”weixin://”將無法識別,報:ERR_UNKNOWN_URL_SCHEME 錯誤。所以我們可以這樣來寫:

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {

                //LogData.i("WebView==url:", url);
                if (url == null) return false;

                try {
                    if (!url.startsWith("http://") && !url.startsWith("https://")) {
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                        startActivity(intent);
                        return true;
                    }
                } catch (Exception e) {//防止crash (如果手機上沒有安裝處理某個scheme開頭的url的APP, 會導致crash)
                    return true;//沒有安裝該app時,返回true,表示攔截自定義鏈接,但不跳轉,避免彈出上面的錯誤頁面
                }


                //返回值是true的時候控制去WebView打開,爲false調用系統瀏覽器或第三方瀏覽器
                view.loadUrl(url);
                return true;
            }
        });

在Android N中 shouldOverrideUrlLoading(WebView view, String url)已經過時,改爲shouldOverrideUrlLoading(WebView view, WebResourceRequest request),我們可以通過request.getUrl()來獲取url。

             @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                return super.shouldOverrideUrlLoading(view, request);
            }

2、onPageStarted(WebView view, String url, Bitmap favicon)

該方法和onPageFinished(WebView view, String url)一起來看,和字面意思一樣,onPageStarted是開始加載時調用,onPageFinished是加載完成後調用。所以我們可以用來做一些加載進度處理,比如說;開始時顯示dialog,加載完畢時隱藏dialog

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {

    super.onPageStarted(view, url, favicon);
    mProgressDialog.show();

 }

 @Override
public void onPageFinished(WebView view, String url) {
  super.onPageFinished(view, url);
  mProgressDialog.hide();

 }

3、onReceivedError (WebView view, int errorCode,String description, String failingUrl)

加載錯誤的時候會回調,在其中可做錯誤處理,比如再請求加載一次,或者顯示自定義錯誤頁面

參數:

WebView view:當前的WebView實例
int errorCode:錯誤碼
String description:錯誤描述
String failingUrl:當前出錯的URL

4、onReceivedSslError (WebView view, SslErrorHandler handler,SslError error)

我們知道HTTPS協議是通過SSL來通信的,所以當使用HTTPS通信的網址(以https://開頭的網站)出現錯誤時,就會通過onReceivedSslError回調通知過來

參數:

WebView view:當前的WebView實例

SslErrorHandler handler:當前處理錯誤的Handler,它只有兩個函數SslErrorHandler.proceed()和SslErrorHandler.cancel(),SslErrorHandler.proceed()表示忽略錯誤繼續加載,SslErrorHandler.cancel()表示取消加載。在onReceivedSslError的默認實現中是使用的SslErrorHandler.cancel()來取消加載,所以一旦出來SSL錯誤,HTTPS網站就會被取消加載了,如果想忽略錯誤繼續加載就只有重寫onReceivedSslError,並在其中調用SslErrorHandler.proceed()

SslError error:當前的的錯誤對象,SslError包含了當前SSL錯誤的基本所有信息

默認加載SSL出錯的網站會出現空白頁面 ,這個時候我們可以這樣來做:

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
//      一定要註釋掉!    
//      super.onReceivedSslError(view, handler, error);
        handler.proceed();
}

我們這裏註釋掉super.onReceivedSslError(view, handler, error);是爲了取消系統的默認行爲(系統默認是調用handler.cancel();來取消加載),然後調用handler.proceed()來忽略錯誤繼續加載頁面。

注意:
當出現SSL錯誤時,WebView默認是取消加載當前頁面,只有去掉onReceivedSslError的默認操作,然後添加SslErrorHandler.proceed()才能繼續加載出錯頁面

當HTTPS傳輸出現SSL錯誤時,錯誤會只通過onReceivedSslError回調傳過來,不會執行onReceivedError

5、shouldInterceptRequest (WebView view, String url)

該函數會在請求資源前調用,每一次請求資源時(如:超鏈接、圖片等)都會通過這個函數來回調。需要注意的是:該函數是在非主線程進行的,所以在其中不能直接做UI操作,如需操作則可以通過handle來實現。如果不想處理直接返回null,讓它繼續加載資源

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章