设置WebView的loadURLTImeOutValue

25

我正在使用PhoneGap和Android,将我的.html和js文件存储在外部服务器上。当我使用以下代码时,应用程序加载我的外部.html文件,并且一切正常:

this.setIntegerProperty("loadUrlTimeoutValue", 60000);
this.loadUrl("http://www.myserver.com");

但是,当通过 WebView 工作时,我似乎无法为 WebView 设置 loadURLTimeoutValue:

private WebView webView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);  

try {
     webView = (WebView) findViewById(R.id.webview);    
     webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
     webView.loadUrl("http://www.myserver.com");     
}

这行代码不起作用。我该如何在WebView上设置超时时间?

6个回答

27

这是一种模拟所描述行为的解决方法。您可以使用WebViewClient,并覆盖onPageStarted方法:

public class MyWebViewClient extends WebViewClient {
    boolean timeout;

    public MyWebViewClient() {
        timeout = true;
    }

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                timeout = true;

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(timeout) {
                    // do what you want
                }
            }
        }).start();
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        timeout = false;
    }
}
如果超时,你可以加载一个错误页面...
要将WebViewClient添加到你的WebView,只需这样做:
webView.setWebViewClient(new MyWebViewClient());

如果出现超时,您可以尝试在if语句内部添加一些控件来验证页面是否已经加载了一半。 - Vito Gentile
3
如果一个页面成功加载并且当线程还未完成运行时,你又加载了另一个页面,就会出现问题... 另外,你的构造函数是不正确的,应该在onPageStarted方法中将超时设置为true! - andreas
2
如何在网站加载失败时取消加载? - Jono
如何处理多次调用onPageFinished的情况 - Amit Verma
这对于多个并发调用是行不通的。一个调用会干扰其他调用。 - Sazzad Hissain Khan
该方法不起作用,在连接超时的情况下,pageStarted事件会在网络超时结束时触发。 - Tobia

16

我使用这个代码为我的WebView设置了超时时间:

public class MyWebViewClient extends WebViewClient {

    boolean timeout = true;

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        Runnable run = new Runnable() {
            public void run() {
                if(timeout) {
                    // do what you want
                    showAlert("Connection Timed out", "Whoops! Something went wrong. Please try again later.");
                }
            }
        };
        Handler myHandler = new Handler(Looper.myLooper());
        myHandler.postDelayed(run, 5000);
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        timeout = false;
    }
}

这里的“myHandler”是指什么?我在尝试你之前的解决方案时,但我想要运行的代码抛出了一个异常,说我需要在UI线程中运行我的代码。你的解决方案使用了“postDelayed”方法,理论上应该在UI线程中运行代码,这样对吗?只是我不明白在“postDelayed”前面的“myHandler”是什么?你能否用“myHandler”代码完善一下例子,或者简单地说明你如何定义“myHandler”代码。 - user280109
myHandler 可能在主(UI)线程中被初始化为 new Handler()。查看 Android 的 Handler 和 Looper 文档以获取更多信息。从文档中不清楚 onPageFinished() 是否会在所有情况下被调用 - 例如,如果发生错误或进行 WebView.stopLoading() 调用。 - MZB
myHandler = new Handler(Looper.myLooper()); - Rodrigo

8
正确的更改默认超时时间的方法是使用config.xml文件中的<preference />标签,例如:
<preference name="loglevel" value="DEBUG" />
<preference name="loadUrlTimeoutValue" value="60000" />
<preference name="errorUrl" value="file:///android_asset/www/connection_error.html" />

如需更多偏好选项,请参考Android配置


这些偏好设置在 Eclipse 中的等效选项是什么? - Heitor

1
如果您扩展CordovaWebView(为了获取phonegap API,应该这样做),则可以使用以下内容:
this.getIntent().putExtra("loadUrlTimeoutValue", 60000);

CordovaWebView 在内部实现了一个超时机制,类似于之前帖子中提出的机制(默认超时时间为 2000)。

请注意,这不是一个文档化的接口,所以它可能在未来被更改。


1
WebView mWebView = findViewById(R.id.web_view);
mWebView.setWebViewClient(new WebViewClient() {
    private volatile boolean timeout;
    private volatile String timeoutOnPageStartedURL;
    private volatile String timeoutCurrentURL;

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);

        timeout = true;
        timeoutOnPageStartedURL = url;
        timeoutCurrentURL = view.getUrl();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (timeout) {
                    view.post(new Runnable() {
                        @Override
                        public void run() {
                            String currentURL = view.getUrl();
                            if ((timeoutOnPageStartedURL.hashCode() == currentURL.hashCode()) ||
                                (timeoutCurrentURL.hashCode() == currentURL.hashCode())) {
                                // do what you want with UI   
                            }                                     
                        }
                    });
                }
            }
        }).start();
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);

        timeout = false;
    }
});

1
这是唯一对我有效的解决方案,因为我需要更新UI,并从字符串数组中加载不同的URL。 - Ahmed Awadallah

0

使用Thread类打扰我,因为从run函数调用WebView将导致异常,因为WebView是在另一个线程中创建和使用的。 我会使用AsyncTask来执行此操作。 在此示例中,我使用AsyncTask将错误文件加载到WebView中,如果超时,则在WebView中加载。如果页面正确加载,则取消AsyncTask。 onPostExecute在UI线程中运行,因此与WebView交互不存在线程安全问题:

private class CustomWebViewClient extends WebViewClient {
    boolean mPageLoaded;
    final int mTimeoutLength = 20000;
    WebView mView;
    TimeoutCheck timeoutCheckTask;

    public CustomWebViewClient()
    {
        super();
        mPageLoaded = false;
    }

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        mView = view;

        timeoutCheckTask  = new TimeoutCheck();
        timeoutCheckTask.execute(null,null);
    }

    public void onPageFinished(WebView view, String url) {
        mPageLoaded = true;
        timeoutCheckTask.cancel(true);
    }

    private class TimeoutCheck extends AsyncTask<Void, Void, Void> {
        protected Void doInBackground(Void... params) {
            long count = 0;
            while (count < mTimeoutLength)
            {
                try
                {
                    Thread.sleep( 1000 );
                }
                catch ( InterruptedException e )
                {
                    e.printStackTrace();
                }

                // Escape early if cancel() is called
                if (isCancelled()) break;
                count += 1000;
            }
            return null;
        }

        protected void onPostExecute(Void result) {
            if(!mPageLoaded) {
                mbLoadedErrFile = true;
                //load error file into the webview
                mView.loadUrl("file:///android_asset/url_err_timeout.html");
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接