【问题标题】:ViewPager + FragmentStatePagerAdapter + orientation changeViewPager + FragmentStatePagerAdapter + 方向改变
【发布时间】:2012-12-04 08:27:00
【问题描述】:

我有一个小问题:我有一个带有一些页面的 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;
    }

如果您需要更多内容,请告诉我。谢谢

【问题讨论】:

标签: android caching android-viewpager adapter fragment


【解决方案1】:

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

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

不要使用 mViewPager.setSaveEnabled(false);

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

【讨论】:

  • 我必须验证 setSaveEnabled 是否导致我进行了 6 小时的内存泄漏调试。
  • 抱歉这么晚才问,但你有没有发现 super.onSaveInstanceState(outState) 中的什么导致了这种意外行为?提前致谢 ! ;-)
  • 是的,已经很晚了 :-) 在 onSaveInstanceState 中,它将片段保存在一个永远不会被清理的数组中。如果不调用 super,它不会将片段保存在此数组中。
  • @Informatic0re 我有查看寻呼机状态问题,但情况不一样。我的问题是here。我按照你的回答做了,但它不起作用。
  • 也解决了我的问题。对于我的情况,这是关于 SO 的最有用的信息之一。非常感谢!
【解决方案2】:

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

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

例子:activity有4个片段,经过4次方向改变,列表FragmentManager.getFragments()的大小将是20!

我找到了一些解决方案:

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

  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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 我已经实现了 OnPageChangeListener 但我不想在那里完成所有工作。我认为只有一个缓存或我需要清除的东西。也许是 ViewPager 或 FragmentManager。适配器是全新创建的,ViewPage 是使用 findViewById 重新创建的,那么为什么要保存缓存呢?也许它是已保存状态,但我不知道如何删除它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 2015-12-03
    相关资源
    最近更新 更多