onPostExecute中的popBackStack导致IllegalStateException

时间:2013-09-13 05:48:06

标签: android android-fragments android-activity illegalstateexception

道歉这是一篇相当长的帖子,让我先试着解释一下背景:

我已经阅读了很多关于这个主题的帖子(以及关于这个主题的Alex's excellent blog post),一般的结论似乎不是在异步回调中执行片段事务(参见Dianne's post),比如AsyncTask#onPostExecute()

但是我有2例需要这样做:

  1. Activity显示登录Fragment,当用户按下登录按钮时,AsyncTask开始向服务器进行身份验证,然后返回登录成功时,登录{ {1}}已替换为主应用Fragment

  2. 显示主应用程序片段的Fragment,当用户触发需要登录的某个操作时,登录片段将替换添加到backstack的主片段。再次按下登录按钮时,Activity将对服务器进行身份验证,然后当登录成功时,我们要弹出backstack以向用户显示主AsyncTask并让他们执行他们想要执行的操作。

  3. 案例1可以使用Fragment来解决,但案例2很棘手,因为commitAllowingStateLoss中没有这种popBackStack的风格。

    在任何情况下,这两种情况都需要特殊处理应用程序在FragmentManager期间转到后台,导致在应用程序处于后台时调用AsyncTask#doInBackground()。一种解决方案是使用Fragment.isResumed来保护替换片段或pop backstack,然后通过再次登录来处理进程被杀死的情况,或者保存一些标志,指示最近成功登录并在应用程序恢复状态下替换/弹出登录片段(login {{ 1}}由onPostExecute()恢复到顶部。或者允许状态丢失,并处理进程终止然后恢复的情况,检查最近的登录并删除登录片段。

    这是你怎么处理的?感觉就像处理一种非常常见的情况一样。

2 个答案:

答案 0 :(得分:5)

最近的解决方法是在FragmentActivity.onStateNotSaved()之前致电popBackStack()

答案 1 :(得分:1)

与上面评论中提到的x90一样,最简单的解决方案是将您的片段拆分为单独的活动。这显然会避免异常,因为启动新活动不需要修改先前活动的状态。像这样在屏幕内外交换片段可能不是你想要做的......正如他们的名字所暗示的,Fragment s被设计成用作用户界面的“片段”,而不是那么多作为构成用户界面的整个屏幕。 (当然,我并不是说你不是允许以这种方式使用Fragment ...我只是说这不是一个设计Fragment API的目标。

您还可以尝试在AsyncTask中实施某种取消政策。也就是说,如果活动开始进入后台,请立即取消任务。当AsyncTask最终完成时,请确保isCancelled()在执行片段事务之前返回false等。