View not attached to window manager crash

For Dialog created in a Fragment, I use the following code:

ProgressDialog myDialog = new ProgressDialog(getActivity());
myDialog.setOwnerActivity(getActivity());
...
Activity activity = myDialog.getOwnerActivity();
if( activity!=null && !activity.isFinishing()) {
    myDialog.dismiss();
}

I use this pattern to deal with the case when a Fragment may be detached from the Activity.


See how the Code is working here:

After calling the Async task, the async task runs in the background. that is desirable. Now, this Async task has a progress dialog which is attached to the Activity, if you ask how to see the code:

pDialog = new ProgressDialog(CLASS.this);

You are passing the Class.this as context to the argument. So the Progress dialog is still attached to the activity.

Now consider the scenario: If we try to finish the activity using the finish() method, while the async task is in progress, is the point where you are trying to access the Resource attached to the activity ie the progress bar when the activity is no more there.

Hence you get:

java.lang.IllegalArgumentException: View not attached to the window manager

Solution to this:

1) Make sure that the Dialog box is dismissed or canceled before the activity finishes.

2) Finish the activity, only after the dialog box is dismissed, that is the async task is over.


Issue could be that the Activity have been finished or in progress of finishing.

Add a check isFinishing , and dismiss dialog only when this is false

if (!YourActivity.this.isFinishing() && pDialog != null) {
    pDialog.dismiss();
}

isFinishing : Check to see whether this activity is in the process of finishing,either because you called finish on it or someone else has requested that it finished.


How to reproduce the bug:

  1. Enable this option on your device: Settings -> Developer Options -> Don't keep Activities.
  2. Press Home button while the AsyncTask is executing and the ProgressDialog is showing.

The Android OS will destroy an activity as soon as it is hidden. When onPostExecute is called the Activity will be in "finishing" state and the ProgressDialog will be not attached to Activity.

How to fix it:

  1. Check for the activity state in your onPostExecute method.
  2. Dismiss the ProgressDialog in onDestroy method. Otherwise, android.view.WindowLeaked exception will be thrown. This exception usually comes from dialogs that are still active when the activity is finishing.

Try this fixed code:

public class YourActivity extends Activity {

    private void showProgressDialog() {
        if (pDialog == null) {
            pDialog = new ProgressDialog(StartActivity.this);
            pDialog.setMessage("Loading. Please wait...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
        }
        pDialog.show();
    }

    private void dismissProgressDialog() {
        if (pDialog != null && pDialog.isShowing()) {
            pDialog.dismiss();
        }
    }

    @Override
    protected void onDestroy() {
        dismissProgressDialog();
        super.onDestroy();
    }

    class LoadAllProducts extends AsyncTask<String, String, String> {

        // Before starting background thread Show Progress Dialog
        @Override
        protected void onPreExecute() {
            showProgressDialog();
        }

        //getting All products from url
        protected String doInBackground(String... args) {
            doMoreStuff("internet");
            return null;
        }

        // After completing background task Dismiss the progress dialog
        protected void onPostExecute(String file_url) {
            if (YourActivity.this.isDestroyed()) { // or call isFinishing() if min sdk version < 17
                return;
            }
            dismissProgressDialog();
            something(note);
        }
    }
}

Tags:

Android