这个主题有很多不同的 SO 问题与之相关,我知道,但我认为大多数人在问他们的问题时仍然对为什么事情发生在什么时候感到困惑。
我读过 Alex Lockwood关于 Fragment Transactions & Activity State Loss 的文章,尽管他为所有事情提供了明确的论据(阅读文章 - 它确实提供了丰富的信息且易于理解),但他没有为我的情况提供完整的证明 - 使用 AsyncTask
s。
这是我们在应用程序中所做的:
- 用户按下启动
AsycTask
的按钮来调用我们的服务器。 - 使用
Intent.ACTION_CALL
从应用内发起电话调用。 - 通话结束,用户返回应用。
AsyncTask
响应服务器调用响应。- 应用代码处理响应并向用户显示输出。
很明显,当用户接听电话时,我们的应用程序停止了。所以当 AsyncTask
到达 onPostExecute()
并提供服务器调用响应时,我们可能不在实时 Activity 中,它可能在 onSaveInstanceState()
已被调用。
那我该如何解决呢?
我必须通过 AlertDialogFragment
将服务器调用响应的结果传达给用户,但是当我想显示该警报时,我得到了 IllegalStateException。
Alex Lockwood 建议我确保在调用 onSaveInstanceSate()
之后不会发生 fragment 事务 - 即(我认为)不要在应用程序中触发任何内容(例如显示警报),来自 AsycTask
的 onPostExecute()
。
那么什么时候呢?
我是否应该在 onResume()
中做一些事情,比如检查我是否收到了来自 AsyncTask
服务器调用的响应,我应该将其保存到共享首选项而不是而不是处理并向用户呈现结果,如果是,向用户显示该警报?
请指教?
最佳答案
AsyncTask
仍会在 Activity
离开后运行。这意味着当 Activity
不再可见时,可能会调用 onPostExecute()
并且应该在 onPostExecute()
中完成的任何 UI 更改都将被调用导致 Exception
,很可能是 NullPointerException
或 IllegalStateException
。
要解决此问题,您必须自己管理 AsyncTask
,方法是在 Activity 的 onPause()
中将其停止并在 Activity 的 onResume( )
或将任务放置在保留的非 UI Fragment
中。在我看来,这些解决方案有点老套。当在任务执行后修改 UI 时,我强烈建议使用 AsyncTaskLoader
代替 AsyncTask
。 AsyncTaskLoaders 使用 LoaderManager
为您处理 Activity/Fragment 生命周期。
有很多资源可以演示 AsyncTaskLoaders 的正确实现,我在下面列出了其中的一些:
我在我的一个开源应用程序 CrimeTalk Reader 中使用了 AsyncTaskLoader
类,以使用 Jsoup 加载网络数据并将结果放在 ListView
中。使用它的类可以在 Github 上找到.
如果您想在没有 UI 交互的情况下运行长时间运行的任务,您可能需要查看 IntentService类。
关于android - 避免 IllegalStateException “Can not perform this action after onSaveInstanceState",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28894254/