淺談WebView加載過程中的各種異常

最近上手了一個項目,項目中80%的業務都是用H5完成的,雖然我是不建議這樣的做法,但是業務需求就是這樣那就擼起袖子干吧。
言歸正傳,既然用到了這么多的H5頁面,WebView自然就成了項目中使用頻率最多的控件,于是乎我們對WebView進行了一些封裝和優化,這篇文章將會簡單談一談WebView加載過程中可能遇到的各種異常以及處理方法,包括:

1.網絡連接斷開和服務端異常

2.網絡連接正常但無法訪問Internet

3.弱網和服務器長時間無響應

源碼下載地址:https://github.com/Lonely7th/EsBaseWebView

1.網絡連接斷開和服務端異常

這種情況下WebViewClient的執行順序為:onPageStarted()>>onReceivedError()>>onPageFinished()
這類異常相對而言比較容易捕獲,當網絡連接斷開或者服務端返回異常時,WebView會自動捕獲并執行onReceivedError方法。
對于這種情況我們選擇在onReceivedError方法中將加載狀態置為加載失敗,接下來在onPageFinished方法中判斷加載狀態并執行相應的處理。

@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
    super.onReceivedError(view, request, error);
    loadError = true;
}
@Override
public void onPageFinished(WebView view, String url) {
    super.onPageFinished(view, url);
    if(getProgress() >= 100){
        if(loadError){
            onLoadError();
        }else{
            onLoadSuccess();
        }
    }
}

2.網絡連接正常但無法訪問Internet

這種情況下WebViewClient的執行順序為:onPageStarted()>>onPageFinished()
在網絡連接正常但無法訪問Internet的情況下,WebView并不會捕獲異常,并且會執行onPageFinished方法表示加載任務已經完成,這種情況下我們無法通過onReceivedError方法判斷加載失敗的狀態。
對于這種情況,我們需要判斷頁面是否真的已經加載完成并給與用戶正確的提示,我們在WebView每次執行onPageFinished方法時使用ping命令來判斷網絡是否可用,如果網絡可用再根據加載狀態參數做相應的處理。

@Override
public void onPageFinished(WebView view, String url) {
    super.onPageFinished(view, url);
    if(getProgress() >= 100){
         new Thread(new Runnable() {
            @Override
            public void run() {
                if(NetworkUtils.isNetworkConnected(getContext()) && NetworkUtils.isNetworkOnline()){//判斷網絡連接是否異常
                    if(loadError){
                        //加載失敗
                     }else{
                        //加載成功
                    }
               }else{
                    //網絡異常
               }
            }
        }).start();
   }
}

3.弱網和服務器長時間無響應

這種情況下WebViewClient的執行順序為:onPageStarted()>>長時間等待>>onReceivedError()>>onPageFinished()
在服務器長時間無響應的情況下,WebView會在執行完onPageStarted方法后進入長時間等待(大約2分鐘),超過等待時間后會先后執行onReceivedError方法和onPageFinished方法。
從邏輯上看這其實是一種正常的流程,WebView捕獲到請求超時異常后執行onReceivedError方法,之后執行onPageFinished方法完成加載任務,但這套流程的問題在于等待時間過長且無法設置,我們需要自定義請求超時時間。
對于這種情況,我們在onPageStarted方法中創建一個Message并延遲5000ms(超時時間)發送,Message發送后判斷WebView是否已經加載完成,如果未完成則視為請求超時。

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
    super.onPageStarted(view, url, favicon);
    webHandler.sendEmptyMessageDelayed(408, TIMEOUT);
}
private Handler webHandler = new Handler(){
   @Override
   public void handleMessage(Message msg) {
       switch (msg.what){
            case 408://請求超時
                if (getProgress() < 100) {
                   loadError = true;
                   onLoadError();
                }
                break;
       }
    }
};

4.展示異常提示頁面

最后我們談一談如何展示異常提示頁面,當我們捕獲到異常時,展示一個友好的異常提示頁面是有助于提升用戶體驗的,由于WebView繼承自ViewGroup,所以這里我們比較傾向于向WebView中addView的方式。
加載異常:

private void onLoadError(int flag){
    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
    while (getChildCount() >= 1) {
        removeViewAt(0);
    }
    addView(netErrorView, 0, lp);
}

正常加載:

private void onLoadSuccess(){
    while (getChildCount() >= 1) {
        removeViewAt(0);
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • WebView·開車指南 目錄 WebView簡介 WebView基本使用 WebView常用方法 WebSett...
    小莊bb閱讀 3,536評論 3 25
  • Tips 由于WebView的用法實在太多,如果您只是想查詢某個功能的使用——建議Ctrl+F(Commad+F)...
    BugDev閱讀 7,776評論 11 109
  • WebView·開車指南 目錄 WebView簡介 WebView基本使用 WebView常用方法 WebSett...
    南城的人閱讀 4,775評論 0 19
  • WebView·開車指南 2016-08-31BugDev 北京市東城區首席Bug布道師開山之作,一整月交通事故血...
    53c021c38a1d閱讀 848評論 0 1
  • 《道士塔》:以前就對“洞窟文化”中的這個著名事件——敦煌洞窟文物事件有所了解。今天讀了余秋雨老師的文字后,更加有了...
    左佳妮閱讀 928評論 2 3