5

In my app, I am showing a dialog during a long-running background process which is modal.
This dialog is dismissed when android returns from the background task.

final ProgressDialog progressDialog = ProgressDialog.show(activity, "", "Doing something long running", true, true);

new Thread(new Runnable() {
    public void run() {
        someLongRunningCode(); // (not using AsyncTask!)

        activity.runOnUiThread(new Runnable() {
            public void run() {
                progressDialog.dismiss();
            }
        });
    }
}).start();

Now, however, when the user rotates his device while the background process is still running the activity is recreated and thus, the progressdialog gets detached from the activity.
When the long running process is done, android obviously tries to hide the (now detached) progress dialog which then results in an exception: java.lang.IllegalArgumentException: View not attached to window manager.
Is there any way to check if it is safe to dismiss the dialog?

Edit: Or better still, is there any way to attach the existing dialog to the newly created activity?
A new, cloned dialog would be fine aswell.

PureSpider
  • 407
  • 4
  • 21

3 Answers3

3

Just catch the exception and ignore it. Android's decision to restart the activity on rotation makes threads have a few odd exceptions like that. But the end result you want is no dialog box displayed. If you just catch the exception, no dialog box is displayed. So you're good.

If you aren't using a separate layout/drawables for landscape and portrait, you can just override configChange in your manifest for the activity so it doesn't destroy the activity (it will still correctly rotate and resize everything for you). That way the same dialog will be up and you shouldn't get the exception. The other option would require a lot of work around onSaveInstanceState and onRestoreInstanceState, and you'd need to be very careful of timing issues if the thread actually finishes during that time. The whole recreate activity on rotation idea doesn't work well with multithreading.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • Actually, the best solution to me would be if there was any way to attach the existing dialog to the newly created activity, as the task might still be running. Is there a way to do that? Also updated my question to reflect that. – PureSpider Jul 28 '13 at 15:25
  • 1
    If you aren't using a separate layout/drawables for landscape and portrait, you can just override configChange in your manifest for the activity so it doesn't destroy the activity (it will still correctly rotate and resize everything for you). The other option would require a lot of work around onSaveInstanceState and onRestoreInstanceState, and you'd need to be very careful of timing issues if the thread actually finishes during that time. – Gabe Sechan Jul 28 '13 at 15:35
  • 1
    Its political- someone in their organization who thought the recreation on rotation thing was really cool didn't like this method. At the same time, most of their apps (except for the most trivial ones) use it including browser, gmail, etc. However their preferred way does not work well with multithreading, to the point where its almost unusable. – Gabe Sechan Jul 28 '13 at 20:49
  • Feel free to post that insightful information as an answer and I'll gladly accept it. – PureSpider Jul 28 '13 at 23:04
0
if (progressDialog != null) {
    progressDialog.dismiss();
}
Geralt_Encore
  • 3,721
  • 2
  • 31
  • 46
  • Obviously, progressDialog is not null even when detached from the window. Else I would be getting a NPE, right? – PureSpider Jul 28 '13 at 14:51
0

I've faced this issue before and solved using the below code.

private boolean isDialogViewAttachedToWindowManager() {
    if (dialog.getWindow() == null) return false;
    View decorView = progressDialog.getWindow().getDecorView();
    return decorView != null && decorView.getParent() != null;
}
MohamedHarmoush
  • 1,033
  • 11
  • 17