Android AsyncTask blocks UI on orientation change
I have a very strange problem. I have an AsyncTask
which appears to block the UI thread when I rotate the phone.
First, let me state that I'm comfortable with my Activity
being destroyed and recreated on rotation. I save the AsyncTask
in onRetainNonConfigurationInstance()
, detach the Activity from it in onDestroy()
, and reattach to it in onCreate()
using getLastNonConfigurationInstance()
.
This is all fine, as long as the AsyncTask
is doing no heavy work. For example, to debug my problem, I have this, and it works exactly as expected with no UI blocking:
@Override
protected Boolean doInBackground(Void... params) {
boolean success = false;
final DbAdapter dbAdapter = dbService.getAdapter();
try {
// pretend to do some complicated work
Thread.sleep(20000);
success = true;
} catch (Exception e) {
e.printStackTrace();
}
return success;
}
However, if I change it开发者_C百科 to do some actual work in the background, then I get a very long delay between onPause()
being called to start the rotation, and onResume()
being called later in the new orientation. This delay is in the tens of seconds, during which time the UI is in an inconsistent state (old layout cropped in the new orientation) and it seems as if the rotation is blocking on the AsyncTask
. The only change is the two lines inside the try block:
@Override
protected Boolean doInBackground(Void... params) {
boolean success = false;
final DbAdapter dbAdapter = dbService.getAdapter();
try {
// actually do some complicated work
XmlParser parser = new XmlParser(context, dbAdapter);
success = parser.parse(source);
} catch (Exception e) {
e.printStackTrace();
}
return success;
}
The context
is a global application context passed in to the AsyncTask
's constructor, so I don't think I'm accidentally retaining a reference to the outgoing Activity
.
What else could be going wrong?
Possibly your activity is also trying to use dbAdapter
, and you have proper synchronization going on to prevent two threads from using dbAdapter
at the same time.
Possibly your activity is trying to load stuff off of the file system on the main application thread, and your database operations are causing too much contention. On hardware, YAFFS2 is effectively single-threaded for I/O operations.
You can use Traceview to attempt to get more information about what is taking up your time, and you can use StrictMode
on Android 2.2 and higher to see where your activity might be trying to do file I/O on the main application thread.
Also, if your AsyncTask
is converting XML into database entries, perhaps this is a better use of an IntentService
rather than an AsyncTask
.
精彩评论