我有一个非常奇怪的问题。我有一个AsyncTask
,当我旋转手机时,它似乎会阻止UI线程。
首先,让我说明我对Activity
被摧毁并在轮换中重新创建感到满意。我将AsyncTask
保存在onRetainNonConfigurationInstance()
中,在onDestroy()
中将活动与其分离,然后使用onCreate()
在getLastNonConfigurationInstance()
中重新附加到该活动。
只要AsyncTask
没有做繁重的工作,这一切都很好。例如,为了调试我的问题,我有这个,它完全按预期工作,没有UI阻塞:
@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;
}
但是,如果我将其更改为在后台进行一些实际工作,那么在onPause()
被调用以开始旋转之间会有很长的延迟,并且onResume()
在新的后期被调用取向。这个延迟是几十秒,在此期间UI处于不一致状态(旧方向在新方向中被裁剪),似乎旋转在AsyncTask
上阻塞。唯一的变化是try块内的两行:
@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;
}
context
是传递给AsyncTask
构造函数的全局应用程序上下文,所以我不认为我不小心保留了对传出Activity
的引用。 / p>
还有什么可能出错?
答案 0 :(得分:1)
您的活动可能也在尝试使用dbAdapter
,并且您正在进行适当的同步,以防止两个线程同时使用dbAdapter
。
可能您的活动正在尝试从主应用程序线程上的文件系统加载东西,并且您的数据库操作引起了太多争用。在硬件上,YAFFS2实际上是用于I / O操作的单线程。
您可以使用Traceview尝试获取有关占用时间的更多信息,并且可以在Android 2.2及更高版本上使用StrictMode
来查看您的活动可能尝试在哪里执行文件I / O主要的应用程序线程。
此外,如果您的AsyncTask
正在将XML转换为数据库条目,那么可能更好地使用IntentService
而不是AsyncTask
。