最近上手了一個(gè)項(xiàng)目砾跃,項(xiàng)目中80%的業(yè)務(wù)都是用H5完成的,雖然我是不建議這樣的做法片迅,但是業(yè)務(wù)需求就是這樣那就擼起袖子干吧。
言歸正傳皆辽,既然用到了這么多的H5頁面柑蛇,WebView自然就成了項(xiàng)目中使用頻率最多的控件,于是乎我們對WebView進(jìn)行了一些封裝和優(yōu)化驱闷,這篇文章將會簡單談一談WebView加載過程中可能遇到的各種異常以及處理方法耻台,包括:
1.網(wǎng)絡(luò)連接斷開和服務(wù)端異常
2.網(wǎng)絡(luò)連接正常但無法訪問Internet
3.弱網(wǎng)和服務(wù)器長時(shí)間無響應(yīng)
源碼下載地址:https://github.com/Lonely7th/EsBaseWebView
1.網(wǎng)絡(luò)連接斷開和服務(wù)端異常
這種情況下WebViewClient的執(zhí)行順序?yàn)椋簅nPageStarted()>>onReceivedError()>>onPageFinished()
這類異常相對而言比較容易捕獲,當(dāng)網(wǎng)絡(luò)連接斷開或者服務(wù)端返回異常時(shí)空另,WebView會自動捕獲并執(zhí)行onReceivedError方法盆耽。
對于這種情況我們選擇在onReceivedError方法中將加載狀態(tài)置為加載失敗,接下來在onPageFinished方法中判斷加載狀態(tài)并執(zhí)行相應(yīng)的處理。
@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.網(wǎng)絡(luò)連接正常但無法訪問Internet
這種情況下WebViewClient的執(zhí)行順序?yàn)椋簅nPageStarted()>>onPageFinished()
在網(wǎng)絡(luò)連接正常但無法訪問Internet的情況下摄杂,WebView并不會捕獲異常坝咐,并且會執(zhí)行onPageFinished方法表示加載任務(wù)已經(jīng)完成,這種情況下我們無法通過onReceivedError方法判斷加載失敗的狀態(tài)析恢。
對于這種情況畅厢,我們需要判斷頁面是否真的已經(jīng)加載完成并給與用戶正確的提示,我們在WebView每次執(zhí)行onPageFinished方法時(shí)使用ping命令來判斷網(wǎng)絡(luò)是否可用氮昧,如果網(wǎng)絡(luò)可用再根據(jù)加載狀態(tài)參數(shù)做相應(yīng)的處理。
@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()){//判斷網(wǎng)絡(luò)連接是否異常
if(loadError){
//加載失敗
}else{
//加載成功
}
}else{
//網(wǎng)絡(luò)異常
}
}
}).start();
}
}
3.弱網(wǎng)和服務(wù)器長時(shí)間無響應(yīng)
這種情況下WebViewClient的執(zhí)行順序?yàn)椋簅nPageStarted()>>長時(shí)間等待>>onReceivedError()>>onPageFinished()
在服務(wù)器長時(shí)間無響應(yīng)的情況下浦楣,WebView會在執(zhí)行完onPageStarted方法后進(jìn)入長時(shí)間等待(大約2分鐘)袖肥,超過等待時(shí)間后會先后執(zhí)行onReceivedError方法和onPageFinished方法。
從邏輯上看這其實(shí)是一種正常的流程振劳,WebView捕獲到請求超時(shí)異常后執(zhí)行onReceivedError方法椎组,之后執(zhí)行onPageFinished方法完成加載任務(wù),但這套流程的問題在于等待時(shí)間過長且無法設(shè)置历恐,我們需要自定義請求超時(shí)時(shí)間寸癌。
對于這種情況,我們在onPageStarted方法中創(chuàng)建一個(gè)Message并延遲5000ms(超時(shí)時(shí)間)發(fā)送弱贼,Message發(fā)送后判斷WebView是否已經(jīng)加載完成蒸苇,如果未完成則視為請求超時(shí)。
@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://請求超時(shí)
if (getProgress() < 100) {
loadError = true;
onLoadError();
}
break;
}
}
};
4.展示異常提示頁面
最后我們談一談如何展示異常提示頁面吮旅,當(dāng)我們捕獲到異常時(shí)溪烤,展示一個(gè)友好的異常提示頁面是有助于提升用戶體驗(yàn)的,由于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);
}
}