避免 IllegalStateException “在 onSaveInstanceState 之后无法执行此操作”

Avoiding IllegalStateException “Can not perform this action after onSaveInstanceState"

这个主题有很多不同的 SO 问题与之相关,我知道,但我认为大多数人在问他们的问题时仍然对为什么事情发生在什么时候感到困惑。

我读过 Alex Lockwood's article on Fragment Transactions & Activity State Loss,尽管他为所有事情提供了明确的论据(阅读这篇文章 - 它确实提供了丰富的信息且易于理解),但他没有为我的工作提供完整的证明情况 - 使用 AsyncTasks。

这是我们在应用程序中所做的:

  1. 用户按下启动 AsycTask 调用我们服务器的按钮。
  2. 一个 phone 呼叫是从应用内使用 Intent.ACTION_CALL 发起的。
  3. Phone 通话结束,用户 returns 进入应用程序。
  4. AsyncTask 响应服务器调用响应。
  5. 应用程序代码处理响应并向用户显示输出。

很明显,当用户转到 phone 调用时,我们的应用程序停止了。因此,当 AsyncTask 到达 onPostExecute() 并提供服务器调用响应时,我们可能不在实时 activity 中,并且可能在 onSaveInstanceState() 被调用之后。

那我该如何解决呢?

我必须通过 AlertDialogFragment 将服务器调用响应的结果传达给用户,但是当我想显示该警报时,我得到了 IllegalStateException。

Alex Lockwood 建议我确保在调用 onSaveInstanceSate() 之后不会发生片段事务 - 即(我想)不要在应用程序中触发任何内容(例如显示警报),来自 onPostExecute()AsycTask

那么什么时候呢?

我是否应该在 onResume() 中做一些事情,比如检查我是否收到了来自 AsyncTask 服务器调用的响应,我应该将其保存到共享首选项而不是处理并将结果呈现给用户,如果是,向用户显示该警报?

请指教?

Activity 导航离开后,AsyncTask 仍将 运行。这意味着当 Activity 不再可见时可以调用 onPostExecute() 并且应该在 onPostExecute() 中完成的任何 UI 更改将导致 Exception,最有可能是 NullPointerExceptionIllegalStateException.

要解决此问题,您必须自己管理 AsyncTask,方法是在 activity 的 onPause() 中停止它并在 activity 中重新启动它s onResume() 或将任务放在保留的非 UI Fragment 中。在我看来,这些解决方案有点老套。当 UI 将在任务执行后被修改时,我强烈建议使用 AsyncTaskLoader 代替 AsyncTask。 AsyncTaskLoaders 使用 LoaderManager 为您处理 Activity/Fragment 生命周期。

有很多资源可以演示 AsyncTaskLoaders 的正确实现,我在下面列出了其中的一些:

我在我的一个开源应用程序 CrimeTalk Reader 中使用 AsyncTaskLoader class 使用 Jsoup 加载网络数据并将结果放入 ListView .使用它的 class 可以在 Github.

上找到

如果您想在没有 UI 交互的情况下 运行 长时间 运行ning 任务,您可能需要查看 IntentService class.