FragmentPagerAdapter不会在方向更改时重新创建片段?

时间:2012-09-03 22:02:33

标签: android

我有ViewPager(扩展FragmentPagerAdapter),其中包含两个Fragments。我需要的是,当我在其中滑动时,为每个ListView刷新Fragment。为此,我实现了ViewPager.OnPageChangeListener接口(即onPageScrollStateChanged)。为了保留对Fragment的引用,我使用HashTable。我在Fragments方法中将HashTable的引用存储在getItem()中:

  @Override
        public Fragment getItem(int num) {
            if (num == 0) {
                Fragment itemsListFragment = new ItemsListFragment();
                mPageReferenceMap.put(num, itemsListFragment);
                return itemsListFragment;
            } else {
                Fragment favsListFragment = new ItemsFavsListFragment();
                mPageReferenceMap.put(num, favsListFragment);
                return favsListFragment;
            }
        }

因此,当我从一个Fragment切换到另一个onPageScrollStateChanged触发器时,我使用HashTableFragments(刷新)中调用所需的方法:

 public void refreshList() {
        ((ItemsListFragment) mPageReferenceMap.get(0)).refresh();
        ((ItemsFavsListFragment) mPageReferenceMap.get(1)).refresh();
    }

orientation change事件发生之前一切正常。之后是refresh()方法中的代码,即:

public void refresh() {
        mAdapter.changeCursor(mDbHelper.getAll());
        getListView().setItemChecked(-1, true); // The last row from a exception trace finishes here (my class).
    }

结果为IllegalStateException

java.lang.IllegalStateException: Content view not yet created
        at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
        at android.support.v4.app.ListFragment.getListView(ListFragment.java:222)
        at ebeletskiy.gmail.com.passwords.ui.ItemsFavsListFragment.refresh(ItemsFavsListFragment.java:17)

假设确实未创建Content视图,我将boolean方法中的onActivityCreated()变量设置为true并使用if/else条件调用{{1}或者不显示成功创建的活动和内容视图。

然后我正在调试以查看getListView()何时调用FragmentPagerAdapter,并且在getItem()事件之后不会调用该方法。所以看起来它orientation change包含对旧ViewPager的引用。这只是我的假设。

那么,有没有办法强制Fragments再次调用ViewPager,所以我可以使用对当前getItem()的正确引用?可能是其他一些解决方案?非常感谢你。

3 个答案:

答案 0 :(得分:4)

  

然后我正在调试以查看FragmentPagerAdapter何时调用getItem(),并且在方向更改事件之后不会调用该方法。看起来它看起来像ViewPager持有对旧碎片的引用。

应该自动重新创建片段,就像配置更改中的任何片段一样。例外情况是你使用setRetainInstance(true),在这种情况下它们应该是和以前一样的片段对象。

  

那么,有没有办法强制ViewPager再次调用getItem(),所以我可以使用对当前片段的正确引用?

那里的碎片有什么问题?

答案 1 :(得分:0)

我花了几天时间寻找这个问题的解决方案,并找出了很多要点:

  • 使用FragmentPagerAdapter代替FragmentStatePagerAdapter

  • 使用FragmentStatePagerAdapter代替FragmentPagerAdapter

  • 在[{1}}覆盖FragmentPagerAdapter

  • 上返回POSITION_NONE
  • 如果您需要对片段进行动态更改,请不要使用FragmentPagerAdapter

  • 以及许多其他人......

在我的应用中,例如Eugene,我自己管理了已创建片段的实例。我将它保存在一个专门的类中的getItemPosition内,因此片段永远不会被释放,从而加速我的应用程序(但消耗更多资源)。

问题出在我旋转平板电脑(和手机)时。该片段不再调用HashMap<String,Fragment>,我无法对其进行更改。

我真的花了很多时间才真正找到了解决方案,所以我需要与StackOverflow社区分享,他们帮助了我很多次......

解决这个问题的方法虽然很难找到,但很简单:

只需在FragmentPagerAdapter的构造函数中保留对FragmentManager的引用:

getItem(int)

多数民众赞成。它会像魅力一样......

答案 2 :(得分:0)

您可以清除保存的实例状态

    protected void onCreate(Bundle savedInstanceState) {
        clearBundle(savedInstanceState);
        super.onCreate(savedInstanceState, R.layout.activity_car);
    }


    private void clearBundle(Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            savedInstanceState.remove("android:fragments");
            savedInstanceState.remove("android:support:fragments");
            savedInstanceState.remove("androidx.lifecycle.BundlableSavedStateRegistry.key");
            savedInstanceState.remove("android:lastAutofillId");
        }
    }