-1

My code tries to do this:

  • onCreate it creates and instance of an asynctask A
  • onPreExecute of A we make call: showDialog
  • in doInBackground we sleep for a while SystemClock.sleep(1000)
  • onPostExecute we dismiss the dialog then start a new Async Task B
  • Task B does mostly the same by opening a dialog waiting then closing it.

Now when you first open the app things happen as the should: you see two Progress dialogs pop up one after the other, each for a period of time.

However if I rotate the screen at anytime, the next time the activity is created the progress dialogs are created but never dismissed. which makes it impossible to use the UI. If I rotate the screen again, I get an error message about leaked views (the dialogs that dint go away). plus new dialogs are now created and also don't want to go away (be dismissed).

here my code:

public class MainActivity extends ListActivity {

    private static final int REFRESH_DIALOG = 100;
    private Resources resources;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        resources = getResources();
        setContentView(R.layout.listview);
        new CreationWork(this).execute();
        super.onCreate(savedInstanceState);
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case REFRESH_DIALOG:
            String message = resources.getString(R.string.refreshing);
            ProgressDialog refreshDialog = new ProgressDialog(this);
            refreshDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            refreshDialog.setMessage(message + "...");
            refreshDialog.setCancelable(false);
            return refreshDialog;
        default:
            return null;
        }
    }

    private static class CreationWork extends AsyncTask<Void, Void, DatabaseManager> {

        private MainActivity activity;

        public CreationWork(MainActivity activity) {
            this.activity = activity;
        }

        @Override
        protected void onPreExecute() {
            activity.showDialog(MainActivity.REFRESH_DIALOG);
            super.onPreExecute();
        }

        @Override
        protected DatabaseManager doInBackground(Void... params) {
            SystemClock.sleep(10000);
            return null;
        }

        @Override
        protected void onPostExecute(DatabaseManager result) {
            activity.dismissDialog(MainActivity.REFRESH_DIALOG);
            new RefreshWork(activity).execute();
            super.onPostExecute(result);
        }
    }

   static class RefreshWork extends AsyncTask<Void, Void, Cursor> {

        private MainActivity activity;

        public RefreshWork(MainActivity activity) {
            this.activity = activity;
        }

        @Override
        protected void onPreExecute() {
            activity.showDialog(MainActivity.REFRESH_DIALOG);
            super.onPreExecute();
        }

        @Override
        protected Cursor doInBackground(Void... params) {
            SystemClock.sleep(1000);
            return null;
        }

        @Override
        protected void onPostExecute(Cursor result) {
            activity.dismissDialog(MainActivity.REFRESH_DIALOG);
            super.onPostExecute(result);
        }
    }

}

Some debug info:

There are no errors untill a second rotation. which makes sense beacuse if the progress dialogs aren't dismissed between the first and second rotations, they are effectively leaked.

when the app first runs, despite two calls to showDialog, onCreateDialog is called only once (I believe this is the normal behaviour). however after the first rotation and for any subsequent rotation onCreateDalog will be called twice per run.

code shogan
  • 839
  • 2
  • 9
  • 25
  • try this :: http://stackoverflow.com/questions/7344488/android-progressbar-late-loading-when-button-click/7344529#7344529 – Nikunj Patel Sep 12 '11 at 10:09
  • @nik I cant find an answer in your link I'm not sure what I'm even meant to be looking for there, perhaps you could post your suggestion as an answer and then leave a link to that question. thanks – code shogan Sep 12 '11 at 12:56
  • Why do you make the AsyncTasks static. I dont see the need there.. if thats your real(full) code. make them non static. – Ron Sep 12 '11 at 15:17
  • it is to do with my style, unless I have a good reason I always make my nested classes static, they become easier to refactor and move around. Anyway I tried what your saying, but unfortunately even when I make them non static the problem still arises. – code shogan Sep 12 '11 at 15:31
  • and yes this is pretty much the full code for a skeleton project. – code shogan Sep 12 '11 at 15:53

2 Answers2

0

Dismiss the dialog in onDestroy() of the activity. Otherwise check whether the dialog is already showing before calling show(). See if that fixes the issue.

Update

The best option I see for your simple needs is the ProgressDialog. Have you tried it?

ProgressDialog mProgDialog = ProgressDialog.show(YourActivity.this, "", 
                    "Loading. Please wait...", true);

for dismissing in onPostExecute

mProgDialog.dismiss();

Update 2

Im not sure if this will work. Override onCancelled in your Asynctasks and dismiss your progress dialogs there. So when orientation changes and if asynctasks get cancelled by calling cancel then the dialogs will be dismissed. First check if onCancelled is called when activity is destroyed while asynctask is running.

Community
  • 1
  • 1
Ron
  • 24,175
  • 8
  • 56
  • 97
  • I've tried dismissing them on onDestroy to plug the leak, but there was no effect. besides I need to get rid of the dialogs before onDestroy so that the user can interact with the UI. – code shogan Sep 12 '11 at 12:51
  • Did you check if dilog is already displaying before displaying it? – Ron Sep 12 '11 at 12:54
  • You are assuming that I'm directly interfacing with the dialog. i.e dialog.show(). However note that I am using showDialog(int). The implementation of `Android.App.Activity` does that check (I assume). have a closer look at the code I posted. – code shogan Sep 12 '11 at 14:58
  • Yes I've been using those for a while, and even _they_ had their own set of problems requiring me to spend lines and lines to manage them. `onDialogCreate` aims to aliveate this, so I really want to make sure I understand what's going wrong here before going back to direct interaction with dialogs. – code shogan Sep 12 '11 at 15:39
  • update 2: tried that too... no luck. The threads are not being cancelled (used the debugger) anyway – code shogan Sep 12 '11 at 15:46
0

Try to write code for showing dialog on onPrepareDialog (int id, Dialog dialog, Bundle args) method. As per documentation for showDialog, a call to onCreateDialog(int, Bundle) will be made with the same id the first time this is called for a given id.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
Roll no1
  • 1,315
  • 1
  • 16
  • 23