Android WebView的加載超時處理
android項目中有這樣一個需求:android中webView加載網頁時,加 一個鏈接超時處理,翻閱google官方api,非常奇怪的是Google竟然沒有超時的這項設置。隨后又Google到處查閱有沒有現成的例子,結果還 是一無所獲。最后,不得不自己來寫一個。廢話不多說了,直接上代碼。
package com.test.js2java;import java.util.Timer; import java.util.TimerTask;
import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.Window; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient;
public class TestJsActivity extends Activity { private long timeout = 5000;
private WebView mWebView; private Handler mHandler = new Handler(); private Timer timer; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); mWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = mWebView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setAllowFileAccess(true); mWebView.setWebViewClient(new WebViewClient() { /* * 創建一個WebViewClient,重寫onPageStarted和onPageFinished * * * onPageStarted中啟動一個計時器,到達設置時間后利用handle發送消息給activity執行超時后的動作. * */ @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { Log.d("testTimeout", "onPageStarted..........."); // TODO Auto-generated method stub super.onPageStarted(view, url, favicon); timer = new Timer(); TimerTask tt = new TimerTask() { @Override public void run() { /* * 超時后,首先判斷頁面加載進度,超時并且進度小于100,就執行超時后的動作 */ if (TestJsActivity.this.mWebView.getProgress() < 100) { Log.d("testTimeout", "timeout..........."); Message msg = new Message(); msg.what = 1; mHandler.sendMessage(msg); timer.cancel(); timer.purge(); } } }; timer.schedule(tt, timeout, 1); } /** * onPageFinished指頁面加載完成,完成后取消計時器 */ @Override public void onPageFinished(WebView view, String url) { // TODO Auto-generated method stub super.onPageFinished(view, url); Log.d("testTimeout", "onPageFinished+++++++++++++++++++++++++"); Log.d("testTimeout", "+++++++++++++++++++++++++" + TestJsActivity.this.mWebView.getProgress()); timer.cancel(); timer.purge(); } }); mWebView.loadUrl("http://image.baidu.com/i?ct=201326592&cl=2&nc=1&lm=-1&st=-1&tn=baiduimage&istype=2&fm=index&pv=&z=0&word=%D7%C0%C3%E6&s=0"); }
}</pre>
其中要注意的是onPageFinished的兩點,第一點,官方是這樣解釋的:
Notify the host application that a page has finished loading. This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet. To get the notification for the new Picture, use
onNewPicture(WebView, Picture)
.也就是說,程序只認為DOM加載完成就完成了,正在加載的圖片不在這個范圍之內。
第二點是,如果在JS文件中又動態去加載另一JS,onPageFinished方法會在所有的JS全部加載完畢后才調用。
最近又在研究PhoneGap,突然發現它里面也有個超時處理。順便貼上關鍵代碼
public class DroidGap extends Activity implements CordovaInterface { // Flag indicates that a loadUrl timeout occurred int loadUrlTimeout = 0; // LoadUrl timeout value in msec (default of 20 sec) protected int loadUrlTimeoutValue = 20000; ........... // Load URL on UI thread final DroidGap me = this; // Create a timeout timer for loadUrl final int currentLoadUrlTimeout = me.loadUrlTimeout; Runnable runnable = new Runnable() { public void run() { try { synchronized(this) { wait(me.loadUrlTimeoutValue); } } catch (InterruptedException e) { e.printStackTrace(); } // If timeout, then stop loading and handle error if (me.loadUrlTimeout == currentLoadUrlTimeout) { me.appView.stopLoading(); LOG.e(TAG, "DroidGap: TIMEOUT ERROR! - calling webViewClient"); me.webViewClient.onReceivedError(me.appView, -6, "The connection to the server was unsuccessful.", url); } } }; Thread thread = new Thread(runnable); thread.start(); me.appView.loadUrl(url); }
其實兩種方法的基本思路都是在程序里開個線程,然后再一段時間(timeout)后處理超時。至于用哪種,就要看程序中具體的需求了。