web-dev-qa-db-ja.com

ProgressDialog:リークウィンドウを防ぐ方法

ProgressDialogを使用して、デバイスがインターネットからデータをダウンロードしている間にユーザーが対話するのを防ぎます。

クライアントがこのバグを生成するまで、すべてが正常に機能していました。

"07-06 17:10:50.363: ERROR/WindowManager(8821): Activity Android.pixelrain.framework.PixelRainActivity has leaked window com.Android.internal.policy.impl.PhoneWindow$DecorView@463f3e50 that was originally added here
07-06 17:10:50.363: ERROR/WindowManager(8821): Android.view.WindowLeaked: Activity Android.pixelrain.framework.PixelRainActivity has leaked window com.Android.internal.policy.impl.PhoneWindow$DecorView@463f3e50 that was originally added here
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.view.ViewRoot.<init>(ViewRoot.Java:251)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:148)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:91)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.view.Window$LocalWindowManager.addView(Window.Java:424)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.app.Dialog.show(Dialog.Java:241)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.app.ProgressDialog.show(ProgressDialog.Java:107)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.app.ProgressDialog.show(ProgressDialog.Java:90)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.pixelrain.HTTPHelper.DraftHelper.getDraft(DraftHelper.Java:70)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.pixelrain.online.OnlineRetriver.getDraft(OnlineRetriver.Java:312)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.pixelrain.HTTPHelper.DraftButtonGL.loadDraft(DraftButtonGL.Java:72)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.pixelrain.HTTPHelper.DraftButtonGL.isTouched(DraftButtonGL.Java:89)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.pixelrain.opengl.views.game.QuickStartGL.touchEnded(QuickStartGL.Java:160)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.pixelrain.game.GameHandler.onTouchEvent(GameHandler.Java:277)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.pixelrain.opengl.GLSurfaceViewChipmunk.onTouchEvent(GLSurfaceViewChipmunk.Java:27)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.view.View.dispatchTouchEvent(View.Java:3765)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:944)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:944)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.view.ViewGroup.dispatchTouchEvent(ViewGroup.Java:944)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at com.Android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.Java:1701)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at com.Android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.Java:1116)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.app.Activity.dispatchTouchEvent(Activity.Java:2093)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at com.Android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.Java:1685)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.view.ViewRoot.handleMessage(ViewRoot.Java:1802)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.os.Handler.dispatchMessage(Handler.Java:99)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.os.Looper.loop(Looper.Java:144)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Android.app.ActivityThread.main(ActivityThread.Java:4937)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Java.lang.reflect.Method.invokeNative(Native Method)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at Java.lang.reflect.Method.invoke(Method.Java:521)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:868)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:626)
07-06 17:10:50.363: ERROR/WindowManager(8821):     at dalvik.system.NativeStart.main(Native Method)"

これを修正する方法がわかりません。

これを引き起こす原因と解決方法はありますか?

ログはこの行にエラーをトレースバックします:

    progressDialog = ProgressDialog.show(PixelRainActivity.staticThis, "",PixelRainActivity.staticThis.getResources().getString( R.string.draftProgressMessage), true);

私はそれをこれに変更した場合、それは問題を解決しますか:

this.runOnUiThread(new Runnable() {
            public void run() {
                progressDialog = ProgressDialog.show(PixelRainActivity.staticThis, "",PixelRainActivity.staticThis.getResources().getString( R.string.draftProgressMessage), true);
            }
        });
46
Jason Rogers

リークは、おそらく_PixelRainActivity.staticThis_属性に起因しています。アクティビティへの参照を保持している場合、このアクティビティが破棄された後でも、メモリリークが発生します。

修正する最も簡単な方法は、代わりにアプリケーションのContextを使用することです。メソッドの_staticThis = this_行をonCreate()からstaticThis = this.getApplicationContext()に変更し、動作するはずです(そして、staticThisのタイプをContextに変更しますまだそうではない)

17

つかいます:

progressDialog.dismiss();

最終作業中

115
Jimmy Collazos

進捗ダイアログがまだ表示されている場合、onDetachまたはonDestroyで確認する必要がある場合があります。そのようです:

@Override
public void onDetach() {
    if (mProgressDialog != null && mProgressDialog.isShowing())
        mProgressDialog.dismiss();
    super.onDetach();
}
4
Diaconu Nicu

cygnusはshowDialog(MY_INT)を使用することをお勧めします。MY_INTは、その方法で起動する他の同様のダイアログと区別するために選択する定数値です。 dismissDialog(MY_INT)を使用して同じ方法で削除します。 onPauseメソッドから起動しないでください。代わりに、ユーザーが行おうとしているアクティビティのonResumeメソッドからそれを行うことができます。次に、このアクティビティのonCreateDialogメソッドを次のようにオーバーライドします。

@Override
protected Dialog onCreateDialog(int id) {
    if(id == MY_INT) {
        ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Your message string");
        return progressDialog;
    }
    return super.onCreateDialog(id);
}
2
Melinda Green

ProgressDialog.show()を使用する代わりに、使用してみてください

Activity.showDialog()は、自動的にDialogを管理し、リークを防ぎます。

編集:showDialog(int)を呼び出すと、Activity.onCreateDialog(int)がトリガーされ、そこでDialogを作成し、表示したいDialogを返します。

1
cyngus

threadまたはAsyncTaskを使用していて、インターネットからコンテンツをダウンロードしてprogress barDialogFragmentを使用するか、dialogの進行状況をキャンセルする必要があります。Activityは、Asynctask最初のキャンセルAsynctaskで進行状況を表示し、oncancelコールバックメソッドとdismiss進行ダイアログがあります。

Window leak in Activityまたはfragmentは、ウィンドウを追加しようとして実際に発生し、表示中にforegroundに表示されますが、ホームを押すと表示されます一時停止し、onStop()を介して停止します。したがって、あなたのCustomViewは消えたウィンドウにアタッチされたままになります。したがって、システムによれば、customViewは解放されなかったスペースを占有しました。

0
Mahesh

バックグラウンドでインターネットから何かを取得するには、AsyncTaskを使用する方が適切です。ただし、静的コンテキストを渡す必要はありません。そして活動

new YourAsyncTask(context).execute();

上記のようにAsyncTaskを呼び出します

private class YourAsynTask extends AsyncTask<String,Void,String>
{
 private Context context;
 private ProgressDialog progressDialog;

 //pass context in constructor
  public YourAsynTask(Context context)
  {
     this.context = context;
  }

  //show progress in onPre 
  @Override
  protected void onPreExecute()
  {
    //show Progress code here.
    progressDialog = ProgressDialog.show(context, "", "Loading. Please wait...", true);
  }

  //dismiss Progress dialog in onPost
  @Override 
  protected void OnPostExecute(String response)
  {
    if(progressDialog!=null)
     progressDialog.dismiss();
     progressDialog = null;
  }
}
0
Xar E Ahmer

進捗ダイアログとバックグラウンドタスクで同様の問題が発生しました。 AsyncTask( http://Android-developers.blogspot.de/2009/05/painless-threading.html )により、ウィンドウをリークすることなく、よりきれいに両方を行うことができました。

0
Andy Dyer