【问题标题】:Commit fragment in onResume leads to IllegalStateExceptiononResume 中的提交片段导致 IllegalStateException
【发布时间】:2016-12-07 10:00:57
【问题描述】:

有一个带有 ID 列表的列表片段。通过单击一个 ID,一个新的活动 DETAIL_ACTIVITY 将启动并按 ID 从休息服务加载数据。此加载发生在 DETAIL_ACTIVITY 的 onResume 方法中。加载完成后,获取的数据用于显示片段。像这样:

public void onResume(){
  super.onResume();

  fetchById(new Callback(){
      public void success(Item someData){
          SomeFragment fragment = ...
          getSupportFragmentManager().beginTransaction()
                                     .replace(R.id.fragment, fragment)
                                     .commit();
      }
  });
}

这在大多数情况下都有效。但是,当互联网连接速度很慢并且我尚未完成加载时从 DETAIL_ACTIVITY 移回时,它会抛出以下错误:

java.lang.IllegalStateException: 之后无法执行此操作 onSaveInstanceState 在 android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1360) 在 android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1378) 在 android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) 在 android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)

使用

commitAllowingStateLoss()

不修复此错误。对此有何其他想法?

【问题讨论】:

  • 您确定这是导致 IllegalStateException 的代码行 (FragmentTransaction) 吗?

标签: android android-fragments


【解决方案1】:

即使我们解决了这个问题,接下来您将面临一个新的异常“活动已被销毁”,因为您已从活动中移回。这是引发此异常的一段代码。

    private void checkStateLoss() {
        if (mStateSaved) {
            throw new IllegalStateException(
                    "Can not perform this action after onSaveInstanceState");
        }
        if (mNoTransactionsBecause != null) {
            throw new IllegalStateException(
                    "Can not perform this action inside of " + mNoTransactionsBecause);
        }
    }

    public void enqueueAction(Runnable action, boolean allowStateLoss) {
        if (!allowStateLoss) {
            checkStateLoss();
        }
        synchronized (this) {
            if (mDestroyed || mActivity == null) {
                throw new IllegalStateException("Activity has been destroyed");
            }
        ...
     }

解决这个问题的正确方法是,停止在ActivityonPause 方法中下载数据的线程,就像您在onResume 方法中启动它一样。

来自docs

例如,如果您的活动有一个在后台运行的线程 要从网络下载数据,它可能会在 onCreate() 然后在 onDestroy() 中停止线程。

目前库中不包含取消运行改造。对于所有寻找解决方案的人,请参阅

【讨论】:

  • +1 感谢您提供如此全面的信息。我正在使用改造库进行 REST 操作。我不知道如何取消这样的线程。
【解决方案2】:

我打赌你已经解决了你的问题。但如果不是:

片段不能保证在FragmentActivity.onResume() 上恢复。根据 Android 开发人员文档,您应该在 FragmentActivity.onResumeFragment() 中这样做。见:

https://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#onResume()

【讨论】:

  • 谢谢,这对我很有帮助。我什至不知道这种方法的存在。
【解决方案3】:

你有没有试过不调用onSaveInstanceState中的super方法:

@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    // No call to super.onSaveInstanceState
}

【讨论】:

  • 我认为它会抛出异常:SuperNotCalledException
【解决方案4】:

我认为您可以使用 Handler 来重定向线程的结果,然后添加 Fragment 这个。因为线程在内存单独的进程中运行。所以请使用处理程序

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多