Be Careful With Static Stuff on AsyncTask
I was writing a sample app to run on the WIMM One wearable Android device, and I ran into a strange error. The flow was:
-
Run an activity, which detected that we had no data, raised a dialog, and finished once the dialog closed.
-
Along the way, the activity sent a command to an
IntentService
to go get the data. -
The next time you would launch the activity, you would get a warning about “sending message to a Handler on a dead thread”, and the activity would not fully start.
I, being a bit cocky, assumed that the problem was something with the WIMM environment.
Ummmm… not so much. I screwed up. In fact, I had seen reference to this problem before, but never fully appreciated what it meant until I ran into it myself.
The problem was that the load-the-data logic for the activity was using
an AsyncTask
. That, on its own, is not a problem — in fact, it’s
desirable (particularly on environments where you can’t use loaders).
However, AsyncTask
has static data members. And one of the limitations
of those static data members is that they need to be initialized on the
main application thread.
Normally, this is not a problem, as you usually only reference the
AsyncTask
class on the main application thread, when you go to create
your first instance of the task to execute.
In my case, though, I had moved some common logic into a static method
on my AsyncTask
subclass… and I was calling that static method from
the IntentService
in onHandleIntent()
. That was the first time I
referenced my AsyncTask
subclass, and it was on a background thread.
That initialized a static Handler
used by AsyncTask
on the background
thread, not the main application thread.
The error message was pointing out that the AsyncTask
static Handler
was associated with a thread (the one from onHandleIntent()
), which
was now dead.
The solution: simply move the static method elsewhere.
The moral of this story is to be very careful about when you first use
AsyncTask
. Some people have resorted to using a custom Application
object and touching an AsyncTask
subclass in onCreate()
, just to make
sure that it is properly initialized. While IMHO that is not necessary,
you do have to pay attention.
Many thanks to the WIMM team for pointing out my error. You can find out more about this issue on the Android issue tracker.