12

我有一个小问题:我有一个带有一些页面的 ViewPager,我使用 FragmentStatePagerAdapter 来处理数据。例如,在纵向中,ViewPager 有 20 页,而在横向中,ViewPager 只有 10 页。因此,在方向更改时,我创建了一个具有不同数据的新适配器。

这里稍微解释一下原因:我显示一张纵向图像和两张横向图像,但总是计数。如果我有 10 张图片要显示,我有 10 张纵向和 5 张横向(总是两张)。

但是现在我有一个奇怪的错误:当我在索引 5 上的横向并转动设备时,ViewPager 的当前页面设置为 10。如果我再次将其转回,我在第 5 页。如果我现在滑动 ViewPage 到页面10 从不调用适配器的 getItem 方法,ViewPage 向我显示一张纵向图片,而不是横向的两张。这怎么可能发生?适配器或 ViewPager 中是否有缓存?在 Activity 的 onCreate 中,一切都是新创建的,适配器以及 ViewPager 的数据(只是带有路径的字符串)。那么知道如何解决这个非常可怕的“功能”吗?

下面是一些代码:

创建:

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

适配器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;
    }

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

4

3 回答 3

42

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

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

不使用 mViewPager.setSaveEnabled(false);

它最终导致了大内存泄漏。每次改变方向后,它都会将 Fragments 放入 FragmentManager 的数组中,并且从不清理它。因此,在多次更改方向后,它的内存使用量会超过 100mb。我认为使用 onSaveInstanceState 方法是一种更好的方法。

于 2013-01-29T08:41:27.257 回答
2

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

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

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

我找到了一些解决方案:

  1. 不要调用super.onSaveInstanceState()你的Activity,但这似乎不是一个好的解决方案,Fragments 无法保存状态和恢复。

  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()叫了两次。

我仍在寻找完美的解决方案: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

于 2016-10-25T16:24:36.283 回答
-1

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

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

于 2012-12-17T10:18:05.067 回答