我有一个很奇怪的问题。我有一个AsyncTask
,当我旋转手机时,它似乎阻止了UI线程。Android AsyncTask阻止UI方向变化
首先,让我说我很满意我的Activity
被破坏并在轮换时重新创建。我将AsyncTask
保存在onRetainNonConfigurationInstance()
中,将它从onDestroy()
中分离出来,并使用getLastNonConfigurationInstance()
将其重新附加到onCreate()
中。
这很好,只要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
。
还有什么可能会出错?
感谢您指点我正确的方向。这是数据库争夺;长时间运行的数据库操作被包装在一个事务中。如果我禁用交易,它可以正常工作(但需要10倍的时间)。有趣的是,争用不在可见的活动中;我的Activity是Tabhost中的几个中的一个,它是等待数据库解除阻塞的其他活动(在轮换时不可见)之一。 – 2011-03-09 10:05:44
关于你的IntentService建议......这是我的理解,很难将结果传回UI,例如关闭进度对话框。你能指点我一个很好的解释,为什么一个IntentService可能比一个AsyncTask更好? – 2011-03-09 10:10:55
@Graham Borland:在某些情况下,它可能并不比“IntentService”更好。你没有规定在你的问题中需要更新UI。请记住,即使您在用户按下BACK时泄漏了'AsyncTask',后台工作可能无法完成,因为Android可能会在您完成之前终止该流程,因为它可能认为没有其他任何内容可以运行来证明保留处理周围。这就是'IntentService'给你的:一个长时间后台操作的容器,可以在活动消失之后幸免于难并让Android知道一些事情。 – CommonsWare 2011-03-09 13:07:41