WebView线程永不停止(WebViewCoreThread,CookieSyncManager,http [0-3])

时间:2010-01-11 09:45:33

标签: android multithreading webview

我使用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的线程在离开后停止的任何想法 他们的活动?

10 个答案:

答案 0 :(得分: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

答案 1 :(得分: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) {}
     }
 }

答案 2 :(得分: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;
}

答案 3 :(得分:4)

看看这个andev.org帖子(WebViewCoreThread problem)。

查看回复... Re: WebViewCoreThread problem - Postby potatoho

  

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

     

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

我跳过了onPause / onResume,但我实现了webView.pauseTimers()webView.resumeTimers(),它至少可以阻止CPU出血。

我还在我的onPause / onResume上添加了CookieSyncManager.getInstance().stopSync() / startSync

答案 4 :(得分:2)

感谢您提供这些信息,当我按下手机上的锁定按钮时,我遇到了这个问题在我的swf上停止声音,当我按下解锁按钮但是活动仍然不可见时,onPause和onResume仍然播放我的瑞士法郎如果你想在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);
}

答案 5 :(得分:2)

WebView.destroy()怎么样?这似乎是在清理事物或者我没有做任何时髦的反射调用。

答案 6 :(得分:1)

实际上,使用webView.destroy(), onPause(), clear**()无法阻止Webcore及其相关的线程。

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

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

答案 7 :(得分:0)

我不得不调用WebView的onDestroy来专门为webview清除内存。当我们用webview回到这个活动时,我正在加载flash并且它正在杀死我的应用程序。如果你每次使用它都不会破坏你的WebView,那么Flash会让你活着。

答案 8 :(得分:0)

以上的解决方案在三星Galaxy S和Android 2.3.3上都失败了。 但是我尝试了下面的解决方法取得了成功:

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

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

答案 9 :(得分: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");恢复。