View not attached to window manager crash
How to reproduce the bug:
- Enable this option on your device:
Settings -> Developer Options -> Don't keep Activities
. - Press Home button while the
AsyncTask
is executing and theProgressDialog
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:
- Check for the activity state in your
onPostExecute
method. - Dismiss the
ProgressDialog
inonDestroy
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);
}
}
}
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.
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.