ViewPager + FragmentStatePagerAdapter +方向更改

时间:2012-12-17 08:44:14

标签: android caching android-viewpager adapter fragment

我有一点问题:我有一个带有一些Pages的ViewPager,我使用FragmentStatePagerAdapter来处理数据。在肖像中,我有例如20页用于ViewPager,在景观中我只有10页用于ViewPager。因此,在方向更改时,我创建了一个具有不同数据的新适配器。

这里有一个小小的解释原因:我以纵向显示一个图像,在风景中显示两个图像,但总是全部计数。如果我要显示10张照片,我有10张照片,5张照片(总是两张)。

但现在我有一个奇怪的错误: 当我在索引5上的横向并转动设备时,ViewPager的当前页面设置为10.如果我再次将其关闭,我在第5页。如果我现在将ViewPage刷到第10页,适配器的方法getItem是从来没有打过电话,ViewPage给我看了一张肖像画,而不是两幅用于风景画。 怎么会发生这种情况?适配器或ViewPager中是否有缓存?在Activity的onCreate中,一切都是新创建的,适配器以及ViewPager的数据(只是带路径的字符串)。 所以任何想法如何解决这个真正可怕的“功能”?

以下是一些代码:

的onCreate:

    mViewPagerAdapter = new ReaderPageViewAdapter(getSupportFragmentManager(), getBaseContext(), mCurrentDocument.mPages, getResources()
                .getConfiguration().orientation);
    mPageReader = (ReaderViewPager) findViewById(R.id.pager);
    mPageReader.setAdapter(mViewPagerAdapter);

adapter getItem:

    public Fragment getItem(final int index) {
        final PageInfo pageInfo = mPages.get(index);
        final PageFragment pageFragment = (PageFragment) PageFragment
                .instantiate(mContext, pageInfo.mClss.getName(), pageInfo.mArgs);
        return pageFragment;
    }

如果你需要更多东西,请告诉我。感谢

3 个答案:

答案 0 :(得分:41)

您可以覆盖FragmentActivity onSaveInstanceState(),而不是调用方法中的super.onSaveInstanceState()。

@Override
protected void onSaveInstanceState(final Bundle outState) {
    // super.onSaveInstanceState(outState);
}

请勿使用 mViewPager.setSaveEnabled(false);

它结束了一个很大的记忆泄漏。每次更改方向后,它都会将Fragments放入FragmentManager数组中,并且永远不会清除它。因此,多次更改方向后,内存使用量将超过100mb。使用onSaveInstanceState方法是我认为更好的方法。

答案 1 :(得分:0)

我也遇到了这个问题,我找到了原因。

永远屏幕旋转,FragmentManager将保留所有活动托管片段,它不会删除片段如果使用FragmentStatePagerAdapter,您可以使用FragmentManager.getFragments()来检查片段。

示例:活动有4个片段,4次方向更改后,列表FragmentManager.getFragments()大小将 20

我找到了一些解决方案:

  1. 请勿致电super.onSaveInstanceState()您的活动,但它似乎不是一个好的解决方案,碎片无法保存状态并恢复。

  2. 使用FragmentPagerAdapter代替FragmentStatePagerAdapter。 但是在方向改变之后,ViewPager托管的片段被消隐了(其他人是否也有同样的问题?)。但我可以删除Activity.onCreate中的所有片段来修复它。像这样:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FragmentManager fm = getSupportFragmentManager();
        List<Fragment> fragments = fm.getFragments();
        if (fragments != null) {
            FragmentTransaction transaction = fm.beginTransaction();
            for (Fragment fragment : fragments) {
                transaction.detach(fragment).remove(fragment);
            }
            transaction.commitNowAllowingStateLoss();
        }
        ...
    

    但是Fragment.onCreateView()调用了两次。

  3. 我仍然在寻找完美的解决方案:D

    编辑:
    我终于解决了这个问题,我的ViewPager的原因是在onStart之后添加。运行到onStart时,FragmentManager将尝试恢复片段状态。我追溯到FragmentManager,请使用以下代码:

    com/android/support/support-fragment/24.2.1/support-fragment-24.2.1-sources.jar!/android/support/v4/app/FragmentManager.java

    检查突出显示行,f.mContainerId实际上是我的ViewPager ID。然后它将尝试向ViewPager添加片段视图,在我的情况下,ViewPager还没有添加,所以它将被消隐,但片段状态为ATTACHED。在FragmentPagerAdapter.instantiateItem()中,如果添加了片段,它只是attach片段,但片段已经附加,所以它什么都不做:(

    我将ViewPager添加到活动布局XML,它是固定的。

    快乐编码:D

答案 2 :(得分:-1)

只需在viewPager.setonpagechangelistener中使用并实现require代码即可应用您的应用程序,

http://developer.android.com/reference/android/support/v4/view/ViewPager.html