0

I have the following AsyncTask in a Fragment (the example is simplified for showing clearly the error):

private class LoginTask extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... params) {

        // Do network login
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        FragmentActivity act = (FragmentActivity) getActivity();
        if (act != null && isAdded()) {
            act.getSupportFragmentManager().beginTransaction()
                    .add(new LoginDialogFragment(), "loginMessage").commit();
        }
    }

}

Once, leaving the app while the task was running I received an IllegalStateException: Can not perform this action after onSaveInstanceState.

I suppose it is because I called it between the onSaveInstanceState of the activiy and the unattachment of the fragment from the activity (or because the activity was unattached after the getActivity() call and the add-fragment call.

So how can I avoid this error in the future? Thanks!

Addev
  • 31,819
  • 51
  • 183
  • 302

2 Answers2

4

The isFinishing() method should help you here.

@Override
    protected void onPostExecute(Void result) {
        FragmentActivity act = (FragmentActivity) getActivity();
        if (act != null && !act.isFinishing() && isAdded()) {
            act.getSupportFragmentManager().beginTransaction()
                    .add(new LoginDialogFragment(), "loginMessage").commit();
        }
    }
florianmski
  • 5,603
  • 1
  • 17
  • 14
  • 2
    [`isFinishing()`](http://developer.android.com/reference/android/app/Activity.html#isFinishing()) is set to `false` again once the app is completely exited. It is only true from before `onPause()` until the end of `onDestroy()`. – Cat Sep 09 '12 at 21:01
  • Thanks a million... Can i somehow mark this answer useful more than once.. ? ;))) – Ewoks Nov 21 '13 at 15:45
2

In onPause, onStop, or onDestroy, call .cancel() on the AsyncTask (this may require that your AsyncTask is a member variable in your activity). Then, in your onPostExecute() method, check if the process was cancelled.

protected void onPostExecute(Void result) {
    if (!isCancelled()) { // Do stuff only if not cancelled
        FragmentActivity act = (FragmentActivity) getActivity();
        if (act != null && isAdded()) {
            act.getSupportFragmentManager().beginTransaction()
                    .add(new LoginDialogFragment(), "loginMessage").commit();
        }
    }
    return null;
}

NB: You may want to also check isCancelled() in any loop you have in doInBackground() so you don't keep doing stuff once the person has left the app.

Cat
  • 66,919
  • 24
  • 133
  • 141
  • 1
    Thanks for your answer. Since I dont want to cancel the task but only dont crash I'll use act != null && isAdded() && isResumed() – Addev Sep 09 '12 at 22:38
  • Will onPostExecute() really be called if the task was canceled? The "Cancelling a task" section here suggest that it wont, and that onCancelled would be called instead: https://developer.android.com/reference/android/os/AsyncTask.html – murrayc Mar 16 '17 at 08:58