上個月公司項目需要在WebView中支持超時處理,然后就開始翻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"); } }
其中要注意的是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)后處理超時。至於用哪種,就要看程序中具體的需求了。
