web-dev-qa-db-ja.com

WebViewスレッドが停止しない(WebViewCoreThread、CookieSyncManager、http [0-3])

WebViewを使用して、アプリのアクティビティの1つにインターネットコンテンツを表示します。
問題は、ユーザーがこのアクティビティを終了すると、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でWebページを開くための呼び出しを無効にすると(webView.loadUrl(...))、これらのスレッドは当然開始されないため、アクティビティを終了した後もオンのままになりません。

WebViewのスレッドを、アクティビティを終了した後に停止させる方法に関するアイデアはありますか?

34
Amit Kotlovski

Webビューで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

40
Skymt

私の解決策は、拡張された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) {}
     }
 }
16
diyism

仕事をするクリーンで簡単なソリューション:

@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;
}
13
Bolling

このandev.orgスレッドを見てください( WebViewCoreThread problem )。

応答を参照してください... Re:WebViewCoreThread problem-Postby potatoho

2)フラッシュを一時停止するには、非表示メソッドWebView.onPause()/ WebView.onResume()を呼び出す必要があります。

3)WebViewCoreThreadを一時停止するには、WebView.pauseTimers()/ WebView.resumeTimers()を使用します。

OnPause/onResumeをスキップしましたが、webView.pauseTimers()webView.resumeTimers()を実装し、少なくともCPUブリードを停止しました。

CookieSyncManager.getInstance().stopSync()/startSyncもonPause/onResumeに追加しました。

4
rquinn

WebView.destroy()はどうですか?ファンキーなリフレクションコールをせずに、私や物事を片付けているようです。

2
Dan Carpenter

これらの情報のおかげで、電話のロックボタンを押すと、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);
}
2
Keiichi

実際、webView.destroy(), onPause(), clear**()を使用しても、Webcoreとその関連スレッドを停止することはできません。

実際には、理想的な方法は、WebViewが存在するアクティビティを独立したプロセスに設定して、アクティビティが終了するとWebcoreを含むすべてのスレッドが破棄されるようにすることです。

それが私が採用した方法です。多分それはあなたにも役立ちます。

1
Verdigrass

上記の解決策は、Samsung Galaxy SでAndroid 2.3.3。

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

存在しないhtmlファイルをロードするようにwebviewを強制しています。これは、webviewにクリーンアップを強制するようです。

0
dangel

WebViewのメモリをクリアするには、WebViewのonDestroyを呼び出す必要がありました。私はフラッシュをロードしていましたが、WebViewでこのアクティビティに戻ると、アプリが強制終了していました。 Flashは、使用するたびにWebViewを破壊しなければ、生き生きと食べます。

0
Eric Novins

メソッドを定義します。

_    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");を呼び出して再開します。

0
Ayaz Alifov