Activity has leaked window that was originally added

后端 未结 30 3051
野趣味
野趣味 2020-11-21 05:48

What is this error, and why does it happen?

05-17 18:24:57.069: ERROR/WindowManager(18850): Activity com.mypkg.myP has leaked window com.android.internal.pol         


        
相关标签:
30条回答
  • 2020-11-21 06:11

    here is a solution when you do want to dismiss AlertDialog but do not want to keep a reference to it inside activity.

    solution requires you to have androidx.lifecycle dependency in your project (i believe at the moment of the comment it's a common requirement)

    this lets you to delegate dialog's dismiss to external object (observer), and you dont need to care about it anymore, because it's auto-unsubscribed when activity dies. (here is proof: https://github.com/googlecodelabs/android-lifecycles/issues/5).

    so, the observer keeps the reference to dialog, and activity keeps reference to observer. when "onPause" happens - observer dismisses the dialog, and when "onDestroy" happens - activity removes observer, so no leak happens (well, at least i dont see error in logcat anymore)

    // observer
    class DialogDismissLifecycleObserver( private var dialog: AlertDialog? ) : LifecycleObserver {
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        fun onPause() {
            dialog?.dismiss()
            dialog = null
        }
    }
    // activity code
    private fun showDialog() {
            if( isDestroyed || isFinishing ) return
            val dialog = AlertDialog
                .Builder(this, R.style.DialogTheme)
                // dialog setup skipped
                .create()
            lifecycle.addObserver( DialogDismissLifecycleObserver( dialog ) )
            dialog.show()
    }
    
    
    0 讨论(0)
  • 2020-11-21 06:12

    You're trying to show a Dialog after you've exited an Activity.

    [EDIT]

    This question is one of the top search on google for android developer, therefore Adding few important points from comments, which might be more helpful for future investigator without going in depth of comment conversation.

    Answer 1 :

    You're trying to show a Dialog after you've exited an Activity.

    Answer 2

    This error can be a little misleading in some circumstances (although the answer is still completely accurate) - i.e. in my case an unhandled Exception was thrown in an AsyncTask, which caused the Activity to shutdown, then an open progressdialog caused this Exception.. so the 'real' exception was a little earlier in the log

    Answer 3

    Call dismiss() on the Dialog instance you created before exiting your Activity, e.g. in onPause() or onDestroy()

    0 讨论(0)
  • 2020-11-21 06:12

    I was having the same problem and found this page, and while my situation was different I called finish from a if block before it defined the alert box.

    So, simply calling dismiss wouldn't work (as it hasn't been made yet) but after reading Alex Volovoy's answer and realizing it was the alert box causing it. I tried to add a return statement right after the finish inside that if block and that fixed the issue.

    I thought once you called finish it stopped everything and finished right there, but it doesn't. It seem to go to the end of the block of code it's in then finishes.

    So, if you want to implement a situation where sometimes it'll finish before doing some code you do gotta put a return statement right after the finish or it'll keep on going and and act like the finish was called at the end of the block of code not where you called it. Which is why I was getting all those weird errors.

    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();
    }
    

    If you don't put the return right after I called finish in there, it will act as if you have called it after the alert.show(); and hence it would say that the window is leaked by finishing just after you made the dialog appear, even though that's not the case, it still think it is.

    I thought I'd add this as here as this shows the finish command acted differently then I thought it did and I'd guess there are other people who think the same as I did before I discovered this.

    0 讨论(0)
  • 2020-11-21 06:15

    I triggered this error by mistakenly calling hide() instead of dismiss() on an AlertDialog.

    0 讨论(0)
  • 2020-11-21 06:15

    This happened to me when i am using ProgressDialog in AsyncTask. Actually i am using hide() method in onPostExecute. Based on the answer of @Alex Volovoy i need to use dismiss() with ProgressDialog to remove it in onPostExecute and its done.

    progressDialog.hide(); // Don't use it, it gives error
    
    progressDialog.dismiss(); // Use it
    
    0 讨论(0)
  • 2020-11-21 06:16

    The answers to this question were all correct, but a little confusing for me to actually understand why. After playing around for around 2 hours the reason to this error (in my case) hit me:

    You already know, from reading other answers, that the has X has leaked window DecorView@d9e6131[] error means a dialog was open when your app closed. But why?

    It could be, that your app crashed for some other reason while your dialog was open

    This lead to your app closing because of some bug in your code, which lead to the dialog remaining open at the same time as your app closed due to the other error.

    So, look through your logical. Solve the first error, and then the second error will solve itself

    One error causes another, which causes another, like DOMINOS!

    0 讨论(0)
提交回复
热议问题