AsyncTask 和 FragmentManager 的问题

Posted

技术标签:

【中文标题】AsyncTask 和 FragmentManager 的问题【英文标题】:Issue with AsyncTask and FragmentManager 【发布时间】:2014-06-24 12:18:02 【问题描述】:

我开发了一个应用程序,但用户说该应用程序在特定部分崩溃,我怀疑是罪魁祸首的代码可以在下面找到,但为您提供一些上下文。我有一个充当向导的片段管理器,最后一个片段上是一个提交按钮,单击该按钮时,“处理”来自所有寻呼机片段的数据,然后重定向到确认片段,所有这些都发生在提交按钮之后单击是在异步任务中完成的。另外,如果有任何后果,我会在 AsyncTask 运行时运行一个进度对话框。

//Called from Async Task's "onPostExecute()"
private void callback()

    FragmentManager fragmentManager = getActivity()
            .getSupportFragmentManager();

    fragmentManager.popBackStack("fraud_report", FragmentManager.POP_BACK_STACK_INCLUSIVE);

    Fragment f =  new CompletedFragment();

    Bundle args = new Bundle();

    args.putString("id", reportToSubmit.getReferenceId());

    f.setArguments(args);

    fragmentManager.beginTransaction()
            .replace(R.id.content_frame, f, "completed").commit();

    fragmentManager.executePendingTransactions();



【问题讨论】:

您提到用户正在报告此问题。你的意思是你不能自己重现错误?堆栈跟踪会很有帮助。 我们做不到。他们正在使用 android 4.3 在 Note 2 上进行测试。实际上,我们自己也在等待堆栈跟踪信息(我们已经在测试应用程序中设置了日志记录来记录这一点)。不幸的是,到目前为止,我所要做的就是我上面提到的。 【参考方案1】:

我猜测这可能是什么,特别是如果它难以重现的话。您的问题是您在异步回调之后执行FragmentTransaction,在此期间可能发生任何数量的事情。因此,您无法保证您将处于活动生命周期中的哪个位置。问题是碎片和状态损失。

http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

https://***.com/a/17527246/1856960

例如,用户启动 AsyncTask,然后结束 Activity,启动另一个,或者点击主页按钮。所有这些都会将 Activity 置于后台,并可能触发对 onSaveInstanceState 的调用。 在调用 onSaveInstanceState 后,您不能提交 Fragment Transaction。这是因为FragmentManager 和与之相关的所有状态都已经捆绑在onSaveInstanceState 中,所以如果Activity 被销毁并重新创建,您将丢失您的Fragment Transaction。

至于解决问题,我希望我有一个很好的建议给你。您可以查看FragmentTransaction#commitAllowingStateLoss,但只有在您确定潜在的失败不会对您的应用程序产生负面影响时才应该使用它。有关详细信息,请参阅上面的链接。

【讨论】:

不幸的是,在这一点上,根据文章中的信息,我认为我们可能无法使用 commitAllowingStateLoss。我们应用程序中的几乎每个片段都是静态的,不需要保留状态,但我会继续研究这一点,直到我们得到更多关于用户错误的数据。谢谢。 TBH,我不得不多次使用 commitAllowingStateLoss,因为唯一的其他解决方案是重新架构我们为异步任务所做的一切。如果用户在销毁之前导航回活动,则不会有问题。只有当 Activity 被销毁并且最后一个 Fragment Transaction 丢失时,这才会是一个问题。当 Activity 重新创建自己时,尝试看看是否有办法缓解这种情况。 那么如果所有这些都包含在单个 Activity 中呢?我好奇。那时担心 Activity 破坏甚至是一个担心吗? 如果用户点击home键什么的,把你的Activity放到后台,OS可以随时销毁Activity来回收内存。当用户导航回来时,它将被重新创建(调用 onCreate 等)。在您的情况下,弹出回栈并添加 CompletedFragment 的 Fragment Transaction 将丢失。片段管理器将恢复到调用onSaveInstanceState 时的任何状态。请注意,这不会每次都发生,onSaveInstanceState 必须在 callback 之前调用。这是与操作系统的竞赛。 那么也许我正在尝试解决错误的问题。流程如下:用户在每个视图寻呼机屏幕上填写信息,移动到下一个直到他们到达最后一个并点击提交 - > 异步任务处理信息(显示进度对话框),完成后,调用 onPostExecute 然后将用户移动到 CompletedFragment。那么有没有更清洁的方法来做到这一点?要处理用户输入(发送到服务器),然后在完成后显示一个新的成功屏幕?我还打算销毁视图寻呼机片段,这样如果用户想要填写并提交新向导,它就会被重置。

以上是关于AsyncTask 和 FragmentManager 的问题的主要内容,如果未能解决你的问题,请参考以下文章

Android中的AsyncTask和接口回调使用详解

Android之——AsyncTask和Handler对照

AsyncTask 和 SOAP 网络服务

带有 ProgressDialog 和进度条的 AsyncTask

AsyncTask的原理和缺点

AsyncTask 和 Thread 区别