36

我使用 WebView 在我们的应用程序的一个活动中显示一些互联网内容。
问题是当用户退出这个活动时,WebView 的线程继续运行!
有问题的线程是:

Thread [<17> WebViewCoreThread] (Running)
Thread [<25> CookieSyncManager] (Running)
Thread [<19> http0] (Running)
Thread [<29> http1] (Running)
Thread [<31> http2] (Running)
Thread [<33> http3] (Running)

暂停这些线程中的每一个,并检查它正忙于做什么:

Thread [<17> WebViewCoreThread] (Suspended)
    Object.wait(long, int) line: not available [native method]
    MessageQueue(Object).wait() line: 288
    MessageQueue.next() line: 148
    Looper.loop() line: 110
    WebViewCore$WebCoreThread.run() line: 471
    Thread.run() line: 1060

Thread [<25> CookieSyncManager] (Suspended)
    Object.wait(long, int) line: not available [native method]
    MessageQueue(Object).wait(long) line: 326
    MessageQueue.next() line: 144
    Looper.loop() line: 110
    CookieSyncManager(WebSyncManager).run() line: 90
    Thread.run() line: 1060

Thread [<19> http0] (Suspended)
    Object.wait(long, int) line: not available [native method]
    RequestQueue(Object).wait() line: 288
    ConnectionThread.run() line: 93

我想知道如何告诉Looper每个线程退出。

我尝试调用webView.destroy()活动的onPause()方法,但它没有影响。
当我禁用在 webView ( ) 中打开网页的调用时webView.loadUrl(...),这些线程自然不会启动,因此在离开活动后不会继续。

关于如何WebView在离开活动后停止线程的任何想法?

4

10 回答 10

40

您应该能够通过在 webview 上调用 onPause / onResume 来停止/恢复这些线程。

然而,这些是隐藏的,所以你需要通过反思来做到这一点。以下代码对我有用:

Class.forName("android.webkit.WebView").getMethod("onPause", (Class[]) null).invoke(webView, (Object[]) null);

其中 webView 是 WebView 的实例。

另请参阅:http ://code.google.com/p/android/issues/detail?id=10282

于 2010-08-20T08:31:52.333 回答
16

我的解决方案,在扩展的 webview 类中(在 android 2.2、andriod 2.3、android 3.1 中测试):

 private boolean is_gone = false;
 public void onWindowVisibilityChanged(int visibility) {
     super.onWindowVisibilityChanged(visibility);
     if (visibility == View.GONE) {
         try {
             WebView.class.getMethod("onPause").invoke(this); //stop flash
         } catch (Exception e) {}
         this.pauseTimers();
         this.is_gone = true;
     } else if (visibility == View.VISIBLE) {
         try {
             WebView.class.getMethod("onResume").invoke(this); //resume flash
         } catch (Exception e) {}
         this.resumeTimers();
         this.is_gone = false;
     }
 }
 public void onDetachedFromWindow() { //this will be trigger when back key pressed, not when home key pressed
     if (this.is_gone) {
         try {
             this.destroy();
         } catch (Exception e) {}
     }
 }
于 2011-09-26T10:45:53.610 回答
13

一个干净简单的解决方案可以完成这项工作:

@Override
public void onPause() {
    super.onPause();
    webView.onPause();
    webView.pauseTimers(); //careful with this! Pauses all layout, parsing, and JavaScript timers for all WebViews.
}

@Override
public void onResume() {
    super.onResume();
    webView.onResume();
    webView.resumeTimers();
}

@Override
public void onDestroy() {
    super.onDestroy();
    parentViewGroup.removeAllViews(); //the viewgroup the webview is attached to
    webView.loadUrl("about:blank"); 
    webView.stopLoading();
    webView.setWebChromeClient(null);
    webView.setWebViewClient(null);
    webView.destroy();
    webView = null;
}
于 2014-06-04T18:46:37.707 回答
4

看看这个 andev.org 线程(WebViewCoreThread 问题)。

查看回复... Re: WebViewCoreThread 问题 - Postby potatoho

2) 要暂停 flash,您必须调用隐藏方法 WebView.onPause() / WebView.onResume()。

3) 要暂停 WebViewCoreThread,请使用 WebView.pauseTimers() / WebView.resumeTimers()。

我跳过了 onPause/onResume,但我实现了webView.pauseTimers()并且webView.resumeTimers()它至少停止了 CPU 流血。

我还将CookieSyncManager.getInstance().stopSync()/添加startSync到我的 onPause/onResume 中。

于 2011-03-14T19:25:44.853 回答
2

感谢您提供这些信息,当我按下手机上的锁定按钮时,我在 webView 上的 swf 中暂停声音时遇到了这个问题,当我按下解锁按钮时,onPause 和 onResume 仍然播放我的 swf,但活动仍然不可见,我建议你如果您想在 webView 中暂停和恢复播放 swf 声音,请将它们放在 onWindowFocusChanged 上

@Override
public void onWindowFocusChanged(boolean hasFocus) {
gameView = (WebView) findViewById(R.id.gameView);
    // TODO Auto-generated method stub
    if (hasFocus) {
        try {
            Class.forName("android.webkit.WebView")
                    .getMethod("onResume", (Class[]) null)
                    .invoke(gameView, (Object[]) null);
        } catch (Exception e) {

        }
        gameView.resumeTimers();
        gameView.loadUrl("javascript:setflashfocus()");
    } else {
        try {
            Class.forName("android.webkit.WebView")
                    .getMethod("onPause", (Class[]) null)
                    .invoke(gameView, (Object[]) null);
        } catch (Exception e) {

        }
        gameView.pauseTimers();
    }
    super.onWindowFocusChanged(hasFocus);
}
于 2011-10-13T08:14:03.463 回答
2

WebView.destroy() 呢?这似乎是在清理东西,或者我没有做任何时髦的反射调用。

于 2013-05-17T15:57:05.423 回答
2

实际上,使用webView.destroy(), onPause(), clear**()还不能停止 Webcore 及其相关线程。

实际上,比较理想的方式是将WebView所在的activity设置为一个独立的进程,这样当activity结束时,包括Webcore在内的所有线程都会被销毁。

这就是我采用的方式。也许它对你也有用。

于 2014-05-31T13:12:45.893 回答
0

我不得不调用 WebView 的 onDestroy 来专门为 webview 清除内存。我正在加载 flash,当我们使用 webview 回到这个活动时,它正在杀死我的应用程序。如果您不每次完成 WebView 都销毁它,Flash 就会把您活活吃掉。

于 2011-01-21T18:33:02.883 回答
0

上面的解决方案在带有 Android 2.3.3 的三星 Galaxy S 上对我来说失败了。但我成功尝试了以下解决方法:

    webview.loadUrl("file:///android_asset/nonexistent.html");

我正在强制 webview 加载一个不存在的 html 文件。这似乎迫使 webview 清理东西。

于 2013-05-09T09:57:59.307 回答
0

定义一个方法:

    private void hiddenWebViewMethod(String state){
        if( webView != null ){
            try {
                Method method = WebView.class.getMethod(state);
                method.invoke(webView);
            } catch (Exception e) {
                Log.e("TAG", "Exception: " + e.toString());
                webView.loadData("", "text/html", "utf-8");
            }
        }
    }

然后调用hiddenWebViewMethod("onPause");停止加载,并 hiddenWebViewMethod("onResume");恢复。

于 2015-02-11T14:55:03.737 回答