Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

android

I too get this error sometimes when I dismiss dialog and finish activity from onPostExecute method. I guess sometimes activity gets finished before dialog successfully dismisses.

Simple, yet effective solution that works for me

@Override
protected void onPostExecute(MyResult result) {
    try {
        if ((this.mDialog != null) && this.mDialog.isShowing()) {
            this.mDialog.dismiss();
        }
    } catch (final IllegalArgumentException e) {
        // Handle or log or ignore
    } catch (final Exception e) {
        // Handle or log or ignore
    } finally {
        this.mDialog = null;
    }  
}

Here is my "bullet proof" solution, which is compilation of all good answers that I found on this topic (thanks to @Damjan and @Kachi). Here the exception is swallowed only if all other ways of detection did not succeeded. In my case I need to close the dialog automatically and this is the only way to protect the app from crash. I hope it will help you! Please, vote and leave comments if you have remarks or better solution. Thank you!

public void dismissWithCheck(Dialog dialog) {
        if (dialog != null) {
            if (dialog.isShowing()) {

                //get the Context object that was used to great the dialog
                Context context = ((ContextWrapper) dialog.getContext()).getBaseContext();

                // if the Context used here was an activity AND it hasn't been finished or destroyed
                // then dismiss it
                if (context instanceof Activity) {

                    // Api >=17
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                        if (!((Activity) context).isFinishing() && !((Activity) context).isDestroyed()) {
                            dismissWithTryCatch(dialog);
                        }
                    } else {

                        // Api < 17. Unfortunately cannot check for isDestroyed()
                        if (!((Activity) context).isFinishing()) {
                            dismissWithTryCatch(dialog);
                        }
                    }
                } else
                    // if the Context used wasn't an Activity, then dismiss it too
                    dismissWithTryCatch(dialog);
            }
            dialog = null;
        }
    }

    public void dismissWithTryCatch(Dialog dialog) {
        try {
            dialog.dismiss();
        } catch (final IllegalArgumentException e) {
            // Do nothing.
        } catch (final Exception e) {
            // Do nothing.
        } finally {
            dialog = null;
        }
    }

I may have a workaround.

Was having the same issue, where I am loading lots of items (via the file system) into a ListView via an AsyncTask. Had the onPreExecute() firing up a ProgressDialog, and then both onPostExecute() and onCancelled() (called when the task is cancelled explicitly via AsyncTask.cancel()) closing it via .cancel().

Got the same "java.lang.IllegalArgumentException: View not attached to window manager" error when I was killing the dialog in the onCancelled() method of the AsyncTask (I'd seen this done in the excellent Shelves app).

The workaround was to create a public field in the AsyncTask that contains the ProgressDialog:

public ProgressDialog mDialog;

Then, in onDestroy() when I cancel my AsyncTask, I can also kill the associated dialog via:

AsyncTask.mDialog.cancel();

Calling AsyncTask.cancel() DOES trigger onCancelled() in the AsyncTask, but for some reason by the time that method is called, the View has already been destroyed and thus cancelling the dialog is failing.


Here is the correct solution to solving this problem:

public void hideProgress() {
    if(mProgressDialog != null) {
        if(mProgressDialog.isShowing()) { //check if dialog is showing.

            //get the Context object that was used to great the dialog
            Context context = ((ContextWrapper)mProgressDialog.getContext()).getBaseContext();

            //if the Context used here was an activity AND it hasn't been finished or destroyed
            //then dismiss it
            if(context instanceof Activity) { 
                if(!((Activity)context).isFinishing() && !((Activity)context).isDestroyed()) 
                    mProgressDialog.dismiss();
            } else //if the Context used wasnt an Activity, then dismiss it too
                mProgressDialog.dismiss();
        }
        mProgressDialog = null;
    }
}

Instead of blindly catching all exceptions, this solution addresses the root of the problem: trying to dimiss a dialog when the activity used to initialize the dialog has already been finished. Working on my Nexus 4 running KitKat, but should work for all versions of Android.


i agree a opinion of 'Damjan'.
if you use many dialogs, should close all dialog in onDestroy() or onStop().
then you may be able to reduce the frequency 'java.lang.IllegalArgumentException: View not attached to window manager' exception occurs.

@Override
protected void onDestroy() {
    Log.d(TAG, "called onDestroy");
    mDialog.dismiss();
    super.onDestroy();
}



but little exceed...
to make it more clear, you prevent to show any dialog after onDestroy called.
i don't use as below. but it's clear.

private boolean mIsDestroyed = false;

private void showDialog() {
    closeDialog();

    if (mIsDestroyed) {
        Log.d(TAG, "called onDestroy() already.");
        return;
    }

    mDialog = new AlertDialog(this)
        .setTitle("title")
        .setMessage("This is DialogTest")
        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        })
        .create();
    mDialog.show();
}

private void closeDialog() {
    if (mDialog != null) {
        mDialog.dismiss();
    }
}

@Override
protected void onDestroy() {
    Log.d(TAG, "called onDestroy");
    mIsDestroyed = true;
    closeDialog();
    super.onDestroy();
}


good luck!


Use this.

if(_dialog!=null && _dialog.isShowing())
_dialog.dismiss();

I had the same problem, you can solve it by:

@Override
protected void onPostExecute(MyResult result) {
    try {
        if ((this.mDialog != null) && this.mDialog.isShowing()) {
            this.mDialog.dismiss();
        }
    } catch (final IllegalArgumentException e) {
        // Handle or log or ignore
    } catch (final Exception e) {
        // Handle or log or ignore
    } finally {
        this.mDialog = null;
    }  
}