【问题标题】:commitAllowingStateLoss() in fragment activities片段活动中的 commitAllowingStateLoss()
【发布时间】:2013-06-15 14:22:18
【问题描述】:

我的应用使用片段活动,它仅处于纵向模式,无法旋转屏幕。

本来我是用commit()的方法,但是现在打算不加选择地把这些改成commitAllowingStateLoss()用于片段活动

在不重新评估我使用片段的每个案例的情况下,是否有任何理由不不加选择地执行此操作?

【问题讨论】:

  • 您是否支持 3.0 之前的版本?
  • 查看我的blog post了解更多信息。
  • 一个很好的问题。

标签: android fragment android-fragmentactivity


【解决方案1】:

如果我理解正确,您的意思是:是否有任何理由在不重新评估我使用片段的每个案例的情况下不分青红皂白地这样做?

答案是肯定的 - 如果不仔细重新评估使用片段的每个案例,您不应该这样做。

当然,通过防止由于配置更改(屏幕旋转)而重新启动,您已经消除了一个关键问题区域:即用户可以在调用onSaveInstanceState 之后但在commitAllowingStateLoss 之前旋转屏幕。在这种情况下,UI 的片段或部分可能会丢失。有关此问题的非正式讨论,请参阅post

但在将commit 替换为commitAllowingStateLoss 之前,您应该考虑其他一些情况。

  1. 基本上,onSaveInstanceState 和 commitAllowingStateLoss 之间的任何 UI 更新: Android: IllegalStateException - When is it thrown?

  2. 如果您有任何更新活动 UI 的无头片段,那么它们的某些更新可能会丢失(参见 article)。

  3. Android 可能会“杀死”一个片段,因为手机/标签的资源不足(请参阅此answer)。

当然,如果屏幕旋转被阻止,那么onSaveInstanceState 可能不会被调用,在这种情况下丢失更新的机会窗口就会增加。

如果您决定使用commitAllowingStateLoss,那么您可以采取一些措施来最大程度地降低所涉及的风险:例如考虑在下次重新启动父活动时执行commit / executePendingTransactions(我知道您不想这样做,但其他人可能会阅读this)。

最后(再次以防其他人阅读此内容 - 这与您的情况无关)处理IllegalStateException 可能比从提交转移到commitAllowStateLoss 更安全。例如,您可以坚持提交并处理IllegalStateException。或者,您可能在 Android 中点击了bug,并且可能有解决方法。

【讨论】:

【解决方案2】:
public abstract int commit ()

安排此事务的提交。提交不会立即发生;它将被安排在主线程上的工作,以便在该线程下一次准备好时完成。

事务只能在其包含的活动保存其状态之前使用此方法提交。如果在该点之后尝试提交,则会引发异常。这是因为如果活动需要从其状态恢复,则提交后的状态可能会丢失。请参阅 commitAllowingStateLoss() 了解丢失提交可能没问题的情况。

public abstract int commitAllowingStateLoss ()

在 API 级别 11 中添加

与 commit() 类似,但允许在保存活动状态后执行提交。这很危险,因为如果活动需要稍后从其状态恢复,提交可能会丢失,因此这应该只用于 UI 状态可以在用户上意外更改的情况。

FragmentActivity 限制

在 Honeycomb (3.0) 之前,活动的状态会在暂停前保存。片段是大量的新状态,并且足够动态,以至于人们经常希望它们在暂停和停止之间切换。如果您在保存片段状态后尝试更改片段状态,这些类会引发异常,以避免意外丢失 UI 状态。然而,这在 Honeycomb 之前过于严格,在暂停之前会保存状态。为了解决这个问题,当在 Honeycomb 之前的平台上运行时,如果您在状态保存和正在停止的活动之间更改片段,则不会引发异常。这意味着在某些情况下,如果 Activity 从其上次保存的状态恢复,这可能是用户上次看到之前的快照。

所以,如果您不担心状态损失,我认为您的决定是可以的。 希望对您的决定有所帮助。

【讨论】:

    【解决方案3】:
    try {
        transaction.commit();
    } catch (IllegalStateException e) {
    }
    

    【讨论】:

    • 如果commit()失败,你可能会在执行commitAllowingStateLoss()时得到IllegalStateException: commit already called...所以这不是真正的解决方案
    • 在执行此操作之前请注意,因为 commitAllowingStateLoss() 会导致状态丢失。
    【解决方案4】:

    一个更好的主意是在 OnPostResume 回调中使用 commit(),而不是不加选择地使用 commitAllowingStateLoss()。以下博文提供了详细的解释 http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

    @Override
    protected void onPostResume() {
        super.onPostResume();
        // Commit your transactions here.
    }
    

    【讨论】:

      【解决方案5】:

      你可以像这样覆盖下一个方法

      @Override
      public void supportFinishAfterTransition() {
          finish();
          super.supportFinishAfterTransition();
      }
      

      它对我有用。

      【讨论】:

        猜你喜欢
        • 2017-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多