Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle AsyncTask onPostExecute when paused to avoid IllegalStateException

I appreciate the numerous postings regarding AsyncTask on a rotation change. I have the following problem when using the compatability lib and trying to dismiss a DialogFragment in onPostExecute.

I have a fragment which fires of an AsyncTask which displays a progress DialogFragment, then in onPostExecute dismisses the dialog and then potentially throws up another DialogFragment.

If when the progress dialog is being displayed I put the application into the background I get the following for my fragment:

1) onPause

2) onSaveInstanceState

3) onPostExecute in which I try to dismiss and invoke a dialog.

I get an IllegalStateException because I'm trying to effectively commit a transaction when the activity has saved its state and I understand this.

On a rotation I've assumed (perhaps incorrectly) that I wouldn't get an onPostExecute until the activity has been recreated. However, when putting the application into the background I assumed (definitely incorrectly) that the onPostExectute wouldn't get called while the fragment/activity was paused.

My question is, is my solution to simply detect in onPostExecute that the fragment/activity is paused and simply perform what I need to do in onResume instead? Seems somewhat ugly to me.

Thanks in advance, peter.

Edit 1

Need to support 2.1 and above

Edit 2

I have considered showing the dialog using FragmentTransaction:add and FragmentTransaction:commitAllowingStateLosshowever this isn't without its problems.

like image 720
PJL Avatar asked Nov 03 '11 09:11

PJL


3 Answers

If you need to synchronize your task with the activity lifecycle, I believe that Loaders are exactly what you need. More specifically, you should use AsyncTaskLoader to do the job. So now instead of running an AsyncTask, you launch your loader, then wait for response in a listener. If the activity is paused, you won't get a callback, this part will be managed for you.

There is another way to handle this task: using a fragment which retains its instance. The general idea is that you create a fragment without UI and call setRetainInstance(true). It has a task which is being notified about the activity being available or not. If not, the task's thread suspends until an activity becomes available.

like image 77
Malcolm Avatar answered Nov 01 '22 18:11

Malcolm


Another way of achieving what you require is to implement the PauseHandler class that I documented in this post.

Then in your onPostExecute method call sendMessage() to post your message into the handler.

When your application resumes the action will be handled.

like image 8
quickdraw mcgraw Avatar answered Nov 01 '22 18:11

quickdraw mcgraw


Rather then using BroadcastReceiver, I prefer using bus libraries like guava, otto or eventbus. Their performance is much better then the broadcast receiver implementation.

like image 3
Oguz Ozcan Avatar answered Nov 01 '22 18:11

Oguz Ozcan