Android WebView的加載超時處理


上個月公司項目需要在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)后處理超時。至於用哪種,就要看程序中具體的需求了。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM