web-dev-qa-db-ja.com

元々追加されているウィンドウからアクティビティーがリークしました

このエラーとは何ですか、そしてなぜそれが起こりますか?

05-17 18:24:57.069: ERROR/WindowManager(18850): Activity com.mypkg.myP has leaked window [email protected] that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850): Android.view.WindowLeaked: Activity ccom.mypkg.myP has leaked window [email protected] that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.view.ViewRoot.<init>(ViewRoot.Java:231)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:148)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:91)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.view.Window$LocalWindowManager.addView(Window.Java:424)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.app.Dialog.show(Dialog.Java:239)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.mypkg.myP$PreparePairingLinkageData.onPreExecute(viewP.Java:183)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.os.AsyncTask.execute(AsyncTask.Java:391)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.mypkg.myP.onCreate(viewP.Java:94)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.app.Instrumentation.callActivityOnCreate(Instrumentation.Java:1047)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2544)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:2621)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.app.ActivityThread.access$2200(ActivityThread.Java:126)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1932)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.os.Handler.dispatchMessage(Handler.Java:99)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.os.Looper.loop(Looper.Java:123)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Android.app.ActivityThread.main(ActivityThread.Java:4595)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Java.lang.reflect.Method.invokeNative(Native Method)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at Java.lang.reflect.Method.invoke(Method.Java:521)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:860)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:618)
05-17 18:24:57.069: ERROR/WindowManager(18850):     at dalvik.system.NativeStart.main(Native Method)
1053
Pentium10

アクティビティを終了した後にダイアログを表示しようとしています。

[編集]

この質問は、Google for Android開発者向けのトップ検索の1つです。そのため、コメントから重要な点をいくつか追加します。これは、今後の調​​査担当者にとって、コメントを深く理解することなく役立つ場合があります。

答え1

アクティビティを終了した後にダイアログを表示しようとしています。

答え2

このエラーは状況によっては多少誤解を招く可能性があります(答えはまだ完全に正確です)。つまり、私の場合はAsyncTaskで未処理の例外がスローされ、Activityがシャットダウンし、次にopen progressdialogがこの例外を引き起こしました。 「本当の」例外は、ログの中で少し早かったです。

答え3

アクティビティを終了する前に作成したDialogインスタンスでdismiss()を呼び出します。 onPause()またはonDestroy()で

1416
Alex Volovoy

解決策はDialogを終了する前にviewP.Java:183で作成したActivitydismiss()を呼び出すことです。 onPause()で。 Windowを終了する前に、すべてのDialogsおよびActivitysを閉じてください。

384
molnarm

AsyncTaskを使用している場合は、おそらくそのログメッセージが誤って表示される可能性があります。ログを調べてみると、おそらくAsyncTaskdoInBackground()メソッドに別のエラーがある可能性があります。これは現在のActivityを爆発させることになります。したがって、AsyncTaskが戻ってきたら、あとはそれがわかります。他の何人かのユーザーはすでにここでそれを説明しました:-)

105
ggomeze

私は誤ってAlertDialogに対してhide()の代わりにdismiss()を呼び出すことでこのエラーを引き起こしました。

59
Mark Phillip

Switchステートメントでbreak callステートメントを見逃した場合、(たとえば)AlertDialogを表示した後に誤ってfinish()を呼び出すことによって、単純な/ダムなミスによってこの例外を受け取ることができます。

   @Override
   public void onClick(View v) {
    switch (v.getId()) {
        case R.id.new_button:
            openMyAlertDialog();
            break; <-- If you forget this the finish() method below 
                       will be called while the dialog is showing!
        case R.id.exit_button:
            finish();
            break;
        }
    }

finish()メソッドはActivityを閉じますが、AlertDialogはまだ表示されています。

つまり、スレッド化の問題や複雑なコーディングなどを探してコードをじっと見つめているときに、ツリーの森を見失ってはいけません。時にはそれはちょうど単純なもので、欠けているbreakステートメントのように愚かなことがあります。 :)

53

この問題は、アクティビティを終了した後にダイアログを表示しようとしたときに発生します。

次のコードを書き留めることで、この問題を解決しました。

@Override
public void onDestroy(){
    super.onDestroy();
    if ( progressDialog!=null && progressDialog.isShowing() ){
        progressDialog.cancel();
    }
}

基本的に、どのクラスからprogressDialogを起動したかによって、onDestroyメソッドをオーバーライドしてこの方法を実行します。 「アクティビティがウィンドウからリークした」問題を解決しました。

30
Shoaib Ahmed

この質問に対する答えはすべて正しかったのですが、なぜ私が実際に理解しているのかを少し分かりにくいものにしました。約2時間遊んだ後、このエラーの理由(私の場合)が私を襲った。

他の答えを読んで、has X has leaked window [email protected][]エラーが発生したのは、アプリを閉じたときにダイアログが開いていたことを意味しています。しかし、なぜ?

ダイアログが開いている間に他の理由でアプリがクラッシュした可能性があります

これは、コードにバグがあるためにアプリケーションが閉じられることにつながります。そのため、他のエラーが原因でアプリケーションが閉じられると同時にダイアログが開いたままになります。

だから、あなたの論理を見てください。最初のエラーを解決してから、2番目のエラーが自分自身を解決します enter image description here

DOMINOSのように、あるエラーが別のエラーを引き起こし、それが別のエラーを引き起こします。

25
Ruchir Baronia

私は最近同じ問題に直面しました。

この問題の背後にある理由は、ダイアログが閉じられる前にアクティビティが閉じられていることです。上記が発生するのにはさまざまな理由があります。上記の記事に記載されているものも正しいです。

私は状況に入りました、なぜならスレッドの中で、私は例外を投げていた関数を呼んでいたからです。そのため、ウィンドウは却下されていたため、例外です。

19
Tushar

これは助けになるかもしれません。

if (! isFinishing()) {

    dialog.show();

    }
13
sandy

アクティビティが破棄されたらダイアログを閉じる

@Override
protected void onDestroy()
{
    super.onDestroy();
    if (pDialog!=null && pDialog.isShowing()){
        pDialog.dismiss();
    }
}
12

私は同じあいまいなエラーメッセージを持っていたし、なぜかわからなかった。前の答えからの手がかりを考えて、私はmDialog.finish()への私の非GUI呼び出しをmDialog.dismiss()に変更し、そしてエラーは消えた。これは私のウィジェットの振る舞いには影響しませんでしたが、それは混乱を招き、重要なメモリリークのフラグを立てていた可能性があります。

11
Melinda Green

私は自分のビデオプレーヤーアプリケーションでこれらのログを取得していました。これらのメッセージは、ビデオプレーヤーが閉じている間にスローされました。興味深いことに、私はこれらのログを数回の実行でランダムに取得していました。また、私のアプリケーションはどのprogressdialogにも関わっていません。最後に、私は以下の実装でこの問題を回避しました。

@Override
protected void onPause()
{
    Log.v("MediaVideo", "onPause");
    super.onPause();
    this.mVideoView.pause();
    this.mVideoView.setVisibility(View.GONE);
}

@Override
protected void onDestroy()
{
    Log.v("MediaVideo", "onDestroy");
    super.onDestroy();
}

@Override
protected void onResume()
{
    Log.v("MediaVideo", "onResume");
    super.onResume();
    this.mVideoView.resume();
}

mVideoView.pause()を呼び出し、OnPausevisibilityに設定してGONEをオーバーライドします。こうすれば私は "Activity has leaked window"ログエラー問題を解決できます。

11
InvisiblePoint

私は同じ問題を抱えていてこのページを見つけました、そして私の状況が異なっていた間、私は警告ボックスを定義する前にfinishブロックからifを呼び出しました。

そのため、単にdismissを呼び出しても(まだ行われていないので)うまくいきませんが、 Alex Volovoy's answerを読んでそれを実現する警告ボックスであることに気付いた後に。私はそのifブロックの中の終わりの直後にreturnステートメントを追加しようとしました、そしてそれは問題を修正しました。

私はあなたが終了と呼ばれればそれがすべてを止めて、そしてすぐそこで終えたと思った、しかしそれはそうではない。それはそれが終わったところでそれが終わったコードのブロックの終わりまで行くようです。

そのため、コードを実行する前に終了することがある状況を実装したい場合は、終了直後にreturn文を入力するか、継続して終了後に終了が呼び出されたように動作します。あなたがそれを呼び出した場所ではないコードのブロック。それが、私がそれらすべての奇妙なエラーを起こしていた理由です。

private picked(File aDirectory){
     if(aDirectory.length()==0){
        setResult(RESULT_CANCELED, new Intent()); 
        finish(); 
        return;
    }
     AlertDialog.Builder alert= new AlertDialog.Builder(this); // Start dialog builder
     alert
        .setTitle("Question")
        .setMessage("Do you want to open that file?"+aDirectory.getName());
    alert
        .setPositiveButton("OK", okButtonListener)
        .setNegativeButton("Cancel", cancelButtonListener);
    alert.show();
}

そこにfinishを呼び出した直後にreturnを入れないと、alert.show();の後にreturnを呼び出したのと同じように動作するため、ダイアログを表示した直後に終了することでウィンドウがリークされていると言えます。そうではありません、それはまだだと思います。

これはfinishコマンドが異なる動作をしていることを示しているので、ここにこれを追加したいと思いました。それから私はそれをしたと思っていました。

10
Kit Ramos

これは質問に対する答えではありませんが、トピックに関連しています。

アクティビティがマニフェストで属性を定義している場合

 Android:noHistory="true"

onPause()を実行した後、アクティビティのコンテキストは失われます。したがって、すべてのビューで this コンテキストを使用すると、このエラーが発生する可能性があります。

7
Killer

アラートを表示しようとするだけでなく、アクティビティの特定のインスタンスを終了して新しいアクティビティ/サービスを開始しようとしたり、停止しようとしたときにもアラートを呼び出すことができます。

例:

OldActivity instance;

    oncreate() {
       instance=this;
    }
    instance.finish();
    instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));
6

このコードを試してください:

public class Sample extends Activity(){
@Override
 public void onCreate(Bundle instance){

}
 @Override
    public void onStop() {
        super.onStop();
      progressdialog.dismiss(); // try this
    }

}
5
tinku

ProgressDialogがまだ表示されていたときにアクティビティを終了した問題がありました。

そのため、最初にダイアログを非表示にしてからアクティビティを終了します。

5
LeonS

これは私がProgressDialogAsyncTaskを使っているときに私に起こりました。実は私はonPostExecutehide()メソッドを使っています。 @Alex Volovoyの回答に基づき、onPostExecuteでそれを削除するには、dismiss()ProgressDialogとともに使用する必要があります。

progressDialog.hide(); // Don't use it, it gives error

progressDialog.dismiss(); // Use it
5
SANAT

Activityが事実上finishedになった後にアラートを表示しようとすると、「Activity has leaked window that was originally added...」エラーが発生します。

2つの選択肢があります。

  1. アラートのログインを再考します。実際にアクティビティを終了する前に、dialogdismiss()を呼び出します。
  2. dialogを別のスレッドに入れて、そのthread上で実行します(現在のactivityとは無関係)。
5
Kyle Clegg

doInBackground()関数にエラーがあり、このコードがある場合、これがあります。

最後にダイアログを追加してみてください。最初にdoInBackground()関数をチェックして修正する

protected void onPreExecute() {
     super.onPreExecute();
     pDialog = new ProgressDialog(CreateAccount.this);
     pDialog.setMessage("Creating Product..");
     pDialog.setIndeterminate(false);
     pDialog.setCancelable(true);
     pDialog.show();

 }

 protected String doInBackground(String...args) {
     ERROR CAN BE IS HERE
 }

 protected void onPostExecute(String file_url) {
     // dismiss the dialog once done
     pDialog.dismiss();
5
NickUnuchek

通常、この問題は進行状況ダイアログが原因で発生します。アクティビティに次の方法のいずれかを使用してこれを解決できます。

 // 1):
          @Override
                protected void onPause() {
                    super.onPause();
                    if ( yourProgressDialog!=null && yourProgressDialog.isShowing() )
                  {
                        yourProgressDialog.cancel();
                    }
                }

       // 2) :
         @Override
            protected void onDestroy() {
                super.onDestroy();
                if ( yourProgressDialog!=null && yourProgressDialog.isShowing()
               {
                    yourProgressDialog.cancel();
                }
            }
4

ProgressdialogonPreExecuteメソッドにAsyncTaskオブジェクトを作成する必要があり、dismissメソッドにonPostExecuteオブジェクトを作成する必要があります。

4
ammad

最善の解決策は、try catchにダイアログを追加し、例外が発生したときにダイアログを閉じることです

以下のコードを使用してください

 try {
        dialog.show();
    } catch (Exception e) {
        dialog.dismiss();
    }
3
Ness Tyagi

私の場合は、Androidマニフェストファイルに許可を含めるのを忘れたためです。

どうやって見つけたの? @Bobbyが受け入れられた回答の下にあるコメントで述べているのと同じように、ログまでさらにスクロールすると、例外をスローした最初の理由またはイベントが表示されます。どうやら、「アクティビティが最初に追加されたウィンドウをリークしました」というメッセージは、最初の例外が何であっても、その結果生じた例外にすぎません。

3
Matthew Quiros

以下のコードを試してください、それはあなたが進行状況ダイアログを閉じるとそれはそのインスタンスが利用可能かどうかを確認しますいつでも動作します。

try {
        if (null != progressDialog && progressDialog.isShowing()) {
            progressDialog.dismiss();
            progressDialog = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
2
Developer

ウィンドウリーク例外には2つの理由があります。

1)アクティビティコンテキストが存在しないときにダイアログを表示するには、これを解決するために、アクティビティが存在することが確実である場合にのみダイアログを表示する必要があります。

if(getActivity()!= null && !getActivity().isFinishing()){
        Dialog.show();
}

2)このコードを使用して解決するために、ダイアログを適切に閉じないでください。

@Override
public void onDestroy(){
    super.onDestroy();
    if ( Dialog!=null && Dialog.isShowing() ){
        Dialog.dismiss();
}
}
2
Sherry

progressbarまたはprogressDialogを表示する前に、これを最善の方法で解決します。

if (getApplicationContext().getWindow().getDecorView().isShown()) {

  //Show Your Progress Dialog

}
2
Ali Akram

コード内のどこかで発生した例外のために、アクティビティが突然終了しないようにしてください。一般に、アクティビティがdoinBackgroundメソッドで強制終了に直面し、次にasynctaskがonPostexecuteメソッドに戻ると、非同期タスクで発生します。

1
Manas Ranjan

私によると問題は、アクティビティが終了した直後にダイアログを呼び出そうとしているということです。そのため私ができることは、Handlerを使用してある程度の遅延を与えることです。

 Handler handler=new Handler();
     handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                     dialog.show();
                     //or
                     dialog.dismiss();

                }
            },100);
1
Satish Silveri
  if (mActivity != null && !mActivity.isFinishing() && mProgressDialog != null && mProgressDialog.isShowing()) {
        mProgressDialog.dismiss();
    }
1
androidmalin

バックグラウンドスレッドからトーストを表示しようとしたときにこのエラーが発生しました。 UIスレッドでUI関連のコードを実行することで解決しました

1
Ron____

私は同じ種類の問題を抱えています。エラーはDialogではなくEditTextにありました。私はEdittextの中でAssynctaskの値を変更しようとしていました。私が解決できる唯一の方法は、新しいrunnableを作成することでした。

runOnUiThread(new Runnable(){
      @Override
      public void run() {
       ...        
      }
    });  
0
Squilo

私はこれのための別の解決策があります、そしてそれがあなたに有効であるように思われるかどうか知りたいです:onDestroyで却下するのではなく、それは主要な解決策であるように、私はProgressDialogを拡張します...

public class MyProgressDialog extends ProgressDialog {

  private boolean isDismissed;

  public MyProgressDialog(Context context) {
    super(context);
  }

  @Override
  public void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    dismiss();
  }

  @Override
  public void dismiss() {
    if (isDismissed) {
      return;
    }
    try {
      super.dismiss();
    } catch (IllegalArgumentException e) {
      // ignore
    }
    isDismissed = true;
  }

進行状況ダイアログをメンバーとして保持する必要はなく、ただ発砲(表示)して忘れるので、これはAFAICの方が望ましいです。

0
Kalisky

必ずthis.dialog.showを呼び出してください。 (アクティビティ)

0
Kai Lean

私はまたサルテストを実行するときにWindowLeaked問題に遭遇します。logcatは以下です。

A[email protected]4334fd40 that was originally added here
Android.view.WindowLeaked: Activity com.myapp.MyActivity has leaked window A[email protected]4334fd40 that was originally added here
            at Android.view.ViewRootImpl.<init>(ViewRootImpl.Java:409)
            at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:312)
            at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:224)
            at Android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.Java:149)
            at Android.view.Window$LocalWindowManager.addView(Window.Java:554)
            at Android.support.v7.app.AppCompatDelegateImplV7.openPanel(AppCompatDelegateImplV7.Java:1150)
            at Android.support.v7.app.AppCompatDelegateImplV7.onKeyUpPanel(AppCompatDelegateImplV7.Java:1469)
            at Android.support.v7.app.AppCompatDelegateImplV7.onKeyUp(AppCompatDelegateImplV7.Java:919)
            at Android.support.v7.app.AppCompatDelegateImplV7.dispatchKeyEvent(AppCompatDelegateImplV7.Java:913)
            at Android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.Java:241)
            at com.Android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.Java:2009)
            at Android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.Java:3929)
            at Android.view.ViewRootImpl.deliverKeyEvent(ViewRootImpl.Java:3863)
            at Android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.Java:3420)
            at Android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.Java:4528)
            at Android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.Java:4506)
            at Android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.Java:4610)
            at Android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.Java:171)
            at Android.os.MessageQueue.nativePollOnce(Native Method)
            at Android.os.MessageQueue.next(MessageQueue.Java:125)
            at Android.os.Looper.loop(Looper.Java:124)
            at Android.app.ActivityThread.main(ActivityThread.Java:4898)
            at Java.lang.reflect.Method.invokeNative(Native Method)
            at Java.lang.reflect.Method.invoke(Method.Java:511)
            at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:1008)
            at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:775)
            at dalvik.system.NativeStart.main(Native Method)

私のアクティビティはAppCompatActivityです。そして、アクティビティの下のコードでそれを作り直しました。

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    // added by sunhang : intercept menu key to resove a WindowLeaked error in monkey-test.
    if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) {
        return true;
    }
    return super.dispatchKeyEvent(event);
}
0
sunhang

LiveDataを扱っている場合は、liveData.value = someValueを使用する代わりに値を更新するときにliveData.postValue(someValue)を実行してください。

0
Mark Pazon

私はVideo PlayerのonErrorダイアログを使用していましたが、代わりに頭がおかしくなりました(これらすべての解決策を試してみました)。

DialogFragmenthttp://developer.Android.com/reference/Android/app/DialogFragment.html を選択しました。

内部のDialogFragmentクラスでビルダーの作成を返すことができます。単にonCreateDialogをオーバーライドするだけです。

0
sherpya

たぶんあなたはdialog.findViewByIdの代わりにfindViewByIdをactivityに使っていて、その後OnClickListenerインスタンスにnullをセットしていて、それがおそらく元のエラーを引き起こしたのかもしれません。

0
Deplover

私もしばらくの間この問題に直面していましたが、私の場合はdialogが原因ではなくActionModeが原因ではないことに気付きました。 ActionModeが開いているときにアクティビティを終了しようとすると、この問題が発生します。あなたのアクティビティのonPauseでアクションモードを終了します。

 private ActionMode actionMode;

 @Override
 public void onActionModeStarted(ActionMode mode) {
    super.onActionModeStarted(mode);
    actionMode = mode;
 }

 @Override
 protected void onPause() {
    super.onPause();
    if (actionMode != null) actionMode.finish();
 }
0
Praveena