55

我在容器 Activity 上使用此方法来显示 BFrag

public void showBFrag()
{
    // Start a new FragmentTransaction
    FragmentTransaction fragmentTransaction = mFragmentMgr.beginTransaction();

    if(mBFrag.isAdded())
    {
        Log.d(LOG_TAG, "Show() BFrag");
        fragmentTransaction.show(mBFrag);   
    }
    else
    {
        Log.d(LOG_TAG, "Replacing AFrag -> BFrag");
        fragmentTransaction.replace(R.id.operation_fragments_frame, mBFrag);
    }

    // Keep the transaction in the back stack so it will be reversed when backbutton is pressed
    fragmentTransaction.addToBackStack(null);

    // Commit transaction
    fragmentTransaction.commit();        
}

我从我的容器活动中调用它;首次:

  • 进入 else 语句并 mBFrag 替换 mAFrag。

然后我按下后退按钮:

  • 并且操作相反(显示了 mAFrag 但.. mBFrag 是否被删除?)。

然后我通过从同一个 Activity 调用 showBFrag() 再次前进:

  • 它再次进入 else 语句。(所以我可以推断未添加 mBFrag)
  • 但是我得到了一个Fragment 已经添加了 IllegalStateException ...(那么为什么它没有进入 if 语句呢?)

所以:

  1. 如果我得到一个Fragment 已经添加 IllegalStateException ,为什么 isAdded() 方法不返回 TRUE ?
  2. popBackStack 操作是否完全删除以前添加的片段?
  3. 我误解了什么行为?

编辑:这是异常的完整信息。

06-07 12:08:32.730: ERROR/AndroidRuntime(8576): java.lang.IllegalStateException: Fragment already added: BFrag{40b28158 id=0x7f0c0085}
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at android.app.BackStackRecord.doAddOp(BackStackRecord.java:322)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at android.app.BackStackRecord.replace(BackStackRecord.java:360)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at android.app.BackStackRecord.replace(BackStackRecord.java:352)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at myPackageName.containerActivity.showBFrag() // This line: "fragmentTransaction.replace(R.id.operation_fragments_frame, mBFrag);"
4

11 回答 11

43

最后我的解决方法是执行前一个片段的 remove() 和 add() 新片段。尽管这就是replace() 方法的本意。

但我仍然在猜测为什么 replace() 方法在这种情况下不能正常工作。这真的很奇怪,我想放弃这是因为我误解了某事或做错了什么。

于 2011-06-07T13:44:19.183 回答
12

如果活动的状态已经被保存,那么调用提交就不再安全了。您必须commitAllowingStateLoss()改为打电话。希望这可以帮助!

编辑:好的,我仔细研究了您的问题,问题是您正在尝试添加已添加的片段。即使您使用替换或删除呼叫,您也不能这样做。我发现的唯一解决方法是创建一个片段的新实例并每次都添加它。删除或替换片段后,最好删除对它的所有引用,以便 GC 处理它。

于 2011-06-06T15:04:43.247 回答
8

可能与这个问题没有直接关系,但我也注意到设置到 FragmentTransaction 的转换会导致 IllegalStateException,而不设置转换则不会。

这是此问题的错误:http ://code.google.com/p/android/issues/detail?id=25598

于 2012-02-16T08:43:06.400 回答
2

我用这个:

if (getFragmentManager().findFragmentByTag(newFragment.getClass().getName()) != null) {
   transaction.remove(newFragment);
 }

并添加了片段

MyFragment frag = new MyFragment(); 
transaction.add(R.id.container, frag, MyFragment.class.getName())

MyFragment.class.getName()代表tag

于 2015-06-09T10:10:40.780 回答
1

使用方法 fragment.isAdded() 检查是否已经添加了 frament 相应地替换或添加片段

于 2014-06-06T06:14:58.987 回答
1

在 fragmentTransection.replace() 之后试试这个

fragmentTransection.addToBackStack(null);
fragmentTransection.commitAllowingStateLoss();
于 2015-05-02T11:36:34.163 回答
1

删除解决setOffscreenPageLimitViewpager我的问题。谢谢。

于 2016-08-17T10:36:21.853 回答
0

我试过打电话FragmentTransaction.remove()onTabUnselected()它解决了这个错误。

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    ft.add(R.id.fragment_container, fragment, null);
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    ft.remove(fragment);
}
于 2013-03-11T09:55:31.263 回答
0

这段代码对我来说很好用。试试这个

((MiActivity)getActivity()).addAccount = new AddAccount();
((MiActivity)getActivity()).addAccount.setArguments(params);
fragmentManager = getActivity().getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container((MiActivity)getActivity()).addAccount);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
于 2014-01-04T12:23:48.347 回答
0

通过遍历我的片段并检查 isAdded() 是否为真,然后删除该片段来解决它。更多细节在这里。

于 2014-09-29T06:48:15.703 回答
0

使用 list 保留片段实例,并判断:

        if (!mFragmentTags.contains(fragTag + "")) {
                transaction.add(R.id.tab_main_container, mCurrentFragment, fragTag + "");
}

于 2021-01-17T06:06:44.220 回答