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

时间:2015-03-06 07:47:48

标签: android android-fragments android-asynctask

我知道,这个主题有很多不同的SO问题,但我认为大多数人在问题的同时仍会对事情发生的原因感到困惑。

我已阅读Alex Lockwood关于Fragment Transactions & Activity State Loss的文章,尽管他为所有事情提供了明确的论据(阅读文章 - 它确实内容丰富且易于理解),但他没有提供一个完整的证据解决我的情况 - 使用AsyncTask s。

以下是我们在应用中的操作:

  1. 用户按下一个按钮,启动AsycTask拨打我们的服务器。
  2. 使用Intent.ACTION_CALL从应用内发起电话。
  3. 电话已结束,用户将返回该应用。
  4. AsyncTask以服务器调用响应进行响应。
  5. 应用程序代码处理响应并向用户显示输出。
  6. 很明显,当用户拨打电话时,我们的应用程序已停止。因此,当AsyncTask到达onPostExecute()并提供服务器调用响应时,我们可能不会处于实时活动中,并且可能在调用onSaveInstanceState()之后。

    那么我该如何解决这个问题呢?

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

    Alex Lockwood建议我确保在onSaveInstanceSate()被调用后没有发生任何片段事务 - 即(我想)不会触发应用程序中的任何内容(如显示警报),{{1 onPostExecute()的{​​}

    那么什么时候呢?

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

    请指教?

1 个答案:

答案 0 :(得分:1)

导航AsyncTask后,Activity仍然会运行。这意味着当onPostExecute()不再可见时可能会调用Activity,并且onPostExecute()中应该执行的任何UI更改都会产生Exception,很可能是NullPointerException {1}}或IllegalStateException

要解决此问题,您必须通过在活动的AsyncTask中停止onPause()并在活动的onResume()中重新启动它来管理Fragment,或将任务置于保留的非{} -UI AsyncTaskLoader。在我看来,这些解决方案有点hacky。我强烈建议在任务执行后修改UI时使用AsyncTask代替LoaderManager。 AsyncTaskLoaders使用AsyncTaskLoader来处理Activity / Fragment生命周期。

有很多资源可以证明AsyncTaskLoader的正确实现,我在下面列出了一些:

我在我的一个开源应用程序CrimeTalk Reader中使用ListView类来使用Jsoup加载Web数据并将结果放在{{1}}中。可以在Github上找到使用它的类。

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