IllegalStateException:<MyFragment>当前不在FragmentManager中

mar*_*mor 34 java android illegalstateexception android-fragments android-viewpager

我知道这听起来像是FragmentStatePagerAdapter IllegalStateException的副本:<MyFragment>当前不在FragmentManager中, 但他的解决方案与我的情况无关.

我很少遇到以下崩溃:

java.lang.RuntimeException:无法暂停活动{MyActivity}:

...

引起:java.lang.IllegalStateException:片段MyFragment {40648258 id = 0x7f070051}当前不在android.support.v4.app.FragmentStatePagerAdapter的android.support.v4.app.FragmentManagerImpl.putFragment(MT:516)的FragmentManager中.saveState(MT:185)在android.support.v4.view.ViewPager.onSaveInstanceState(MT:881)

...

在Android.app.Activity.onSaveInstanceState(Activity.java:1138)的com.android.internal.policy.impl.PhoneWindow.saveHierarchyState(PhoneWindow.java:1522)的android.view.View.saveHierarchyState(View.java:6238) )在MyActivity.onSaveInstanceState(MT:336)的android.support.v4.app.FragmentActivity.onSaveInstanceState(MT:480)处

看起来这是我无法理解的奇怪代码FragmentStatePagerAdapter:

for (int i=0; i<mFragments.size(); i++) {
    Fragment f = mFragments.get(i);
    if (f != null) {
        if (state == null) {
            state = new Bundle();
        }
        String key = "f" + i;
        mFragmentManager.putFragment(state, key, f);
    }
}
Run Code Online (Sandbox Code Playgroud)

它看起来像适配器获取我FragmentmFragments但不能添加其状态FragmentManager.

我找不到任何方法在我的测试设备上重新创建它,只是从一些用户那里收到了这个.

我正在使用支持包v4.

有帮助吗?谢谢.

Gre*_*nis 16

FragmentStatePagerAdapter是一段可怕的代码,充斥着谷歌承认与否的错误,因此我使用此代码来修复此特定崩溃:

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // Yet another bug in FragmentStatePagerAdapter that destroyItem is called on fragment that hasnt been added. Need to catch
        try {
            super.destroyItem(container, position, object);
        } catch (IllegalStateException ex) {
            ex.printStackTrace();
        }
    }
Run Code Online (Sandbox Code Playgroud)


piu*_*lte 10

当在ViewPager上设置FragmentStatePagerAdapter时会发生这种情况,其中Fragments正在填充,但由于在ViewPager发生布局之前Activity暂停,因此尚未添加到FragmentManager.通过从onCreate启动另一个Activity可以实现这一点,同时适配器也设置在onCreate中.在这种情况下,最好不要设置适配器,而是将其设置为onActivityResult.请参阅此问题:https://code.google.com/p/android/issues/detail?id = 77285

我还提交了一个补丁来检查在尝试保存状态之前是否添加了Fragment.


Vil*_*usK 7

如果您有片段层次结构,请使用getChildFragmentManager()而不是 getFragmentManager()例如.如果你有片段寻呼机.


小智 7

我遇到了确切的异常.

在我的例子中,我有几个片段由FragmentPagerStateAdapter管理,但有时片段将被切换到位.

我重写getItemPosition()并返回新位置并调用notifyDataSetChanged()来刷新ViewPager.一切正常,但有时当我离开ViewPager时会发生崩溃.

经过几个小时的挖掘,我发现FragmentPagerStateAdapter中存在一个错误.

适配器不仅缓存状态,还缓存它认为"活动"的片段

private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
private ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
Run Code Online (Sandbox Code Playgroud)

但它不会检查碎片的位置是否已失效或移动.

这就是它如何得到这个例外:

1.我在ViewPager和Adapter中有A,B,C三个片段.

2.我将位置切换到适配器中的B,A,C并调用notifyDataSetChanged().

3.ViewPager按新顺序重新布局片段.但是mFragments缓存仍然是{A,B,C}

4.Swipe几页,ViewPager将要求适配器销毁第一个片段.然后在缓存中将片段B而不是A设置为null.现在mFragments是{null,A,C}.

5.离开ViewPager,并触发onSaveInstanceState.mFragments中的所有片段都被认为是活动的,并且调用putFragment()直到FragmentManagerImpl发现A不在其中并抛出异常.

所以这是我不太温和的解决方案:

1.复制整个FragmentPagerStateAdapter源代码.

2.Override notifyDataSetChanged()方法重新排列缓存,如下所示.

@Override
public void notifyDataSetChanged() {
  List<Fragment> oldFragments = new ArrayList<>(mFragments);
  List<Fragment.SavedState> oldStates = new ArrayList<>(mSavedState);
  for (int i = 0; i < getCount(); i++) {
    if (i < mFragments.size()) {
      Fragment f = mFragments.get(i);
      if (f != null) {
        int newPosition = getItemPosition(f);
        if (newPosition == POSITION_UNCHANGED || newPosition == i) {
        } else if (newPosition == POSITION_NONE) {
          if (i < mSavedState.size()) {
            mSavedState.set(i, null);
          }
          mFragments.set(i, null);
        } else {
          while (i >= mFragments.size()) {
            mFragments.add(null);
          }
          if (oldStates.size() > i) {
            mSavedState.set(newPosition, oldStates.get(i));
          }
          mFragments.set(newPosition, oldFragments.get(i));
        }
      } else {
        /*
         * No Fragment but that's possible there's savedState and position has
         * changed.
         */
      }
    }
  }
  super.notifyDataSetChanged();
}
Run Code Online (Sandbox Code Playgroud)

希望对你们有些人有用!


sup*_*ser 0

你可以尝试使用mFragmentManager.add();