开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜