58

我有一个 Fragment(我称之为pagerFragment),它被添加到 backstack 中并且是可见的。它持有 aviewPager和 a FragmentPagerAdapter。持有(FragmentPagerAdapter假设)两个片段:A 和 B。

首先添加片段效果很好。

片段 A 有一个按钮,一旦单击,就会将片段 (C) 添加到后台堆栈。

问题是这样的:如果我添加那个片段 (C),然后单击返回,则它pagerAdapter是空的,我看不到里面的任何片段。

如果我使用 hack 并销毁pagerFragments中的子片段(A 和 B) onDestroyView(),这可以解决问题,尽管我不想使用这个 hack。

任何想法可能是什么问题?

4

5 回答 5

92

我有同样的问题。我的解决方案很简单:

在 onCreateView 我有:

// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity()
    .getSupportFragmentManager());

其中 SectionPageAdapter 是这样的:

class SectionsPagerAdapter extends FragmentPagerAdapter {
...
}

将 getSupportFragmentManager 更改为

mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());

它开始工作了!希望这可以帮助。

于 2013-09-18T13:21:07.863 回答
16

听起来您正在使用嵌套片段,因为您的 ViewPager 位于 PagerFragment 内。您是否将 getChildFragmentManager() 传递给 FragmentPagerAdapter 的构造函数?如果不是,你应该。

我认为您不需要 FragmentStatePagerAdapter,但我会试一试,因为它可以处理保存和恢复 Fragment 状态。您的 onDestroyView() hack 起作用的事实让我认为您可能想要一个 FragmentStatePagerAdapter。

它也可能与 FragmentPagerAdapter 添加 Fragments 的方式有关。FragmentPagerAdapter 不会将 Fragments 添加到 backstack。想象一下,如果您在 ViewPager 中添加了 10 多个页面,并且用户浏览了它们。用户需要回击 11 次才能退出应用程序。

它也可能与这篇文章有关:Nested Fragments and The Back Stack

另外,我不确定您将片段 C 添加到什么。您是否将其添加到与 ViewPager 相同的容器中?

好吧,至少你有几个选择来调查。在这些情况下,我喜欢调试到 Android SDK 源代码,看看是什么导致了这种行为。我建议获取AOSP 源并添加 frameworks/support 和 frameworks/base 作为您的 SDK 源。这是了解正在发生的事情并避免在一切正常之前进行随机更改的唯一真正方法。

于 2013-08-22T15:46:10.280 回答
4

使用getChildFragmentManager()而不是getSupportFragmentManager(). 它会正常工作。

于 2017-12-15T13:26:51.853 回答
1

我也刚刚在我们的项目中遇到了这个问题。根本原因是 FragmentPagerAdapter 的工作方式:

FragmentPagerAdapter 只是将他当前不需要的 Fragment 从其 View 中分离出来,但不会将其从其 FragmentManager 中删除。当他想再次显示 Fragment 时,他使用从 ViewPager 的视图 id 和适配器 getItemId(position) 调用返回的 id 创建的标签查看 FragmentManager 是否仍然包含 Fragment。如果他找到一个 Fragment,他只需在 FragmentManager 的更新事务中安排将 Fragment 附加到其视图。只有当他没有以这种方式找到片段时,他才会使用适配器 getItem(position) 调用创建一个新片段!

包含带有 FragmentPagerAdapter 的 ViewPager 的 Fragment 的问题是,当将包含的 Fragment 放入后堆栈时,FragmentManager 的内容永远不会被清理。如果包含 Fragment 从返回堆栈返回,它会创建一个新视图,但 FragmentManager 仍然包含附加到旧视图的片段,并且现有片段的附加不再起作用。

摆脱这个问题的最简单方法是避免嵌套片段。:)

第二种最简单的方法是在其他帖子中已经提到,将 ChildFragmentManager 用于 FragmentPagerAdapter,因为这个方法在容器片段的生命周期中得到了适当的更新。

由于有些项目(如我目前的项目)无法使用这两个选项,因此我在此处发布了一个解决方案,该解决方案可与任意 FragmentManager 一起使用,方法是将子片段的 hashCode 用作该位置的片段的项目 ID。它是以存储适配器内所有位置的所有片段为代价的。

public class MyPagerAdapter extends FragmentPagerAdapter {

private static int COUNT = ...;
private final FragmentManager fragmentManager;
private Fragment[] subFragments = new Fragment[COUNT];
private FragmentTransaction cleanupTransaction;

public MyPagerAdapter(FragmentManager fragmentManager) {
    super(fragmentManager);
    this.fragmentManager = fragmentManager;
}

@Override
public Fragment getItem(int position) {
    return getSubFragmentAtPosition(position);
}

@Override
public int getCount() {
    return COUNT;
}

@Override
public long getItemId(int position) {
    return getSubFragmentAtPosition(position).hashCode();
}

//The next three methods are needed to remove fragments no longer used from the fragment manager
@Override
public void startUpdate(ViewGroup container) {
    super.startUpdate(container);
    cleanupTransaction = fragmentManager.beginTransaction();
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);
    cleanupTransaction.remove((Fragment) object);
}

@Override
public void finishUpdate(ViewGroup container) {
    super.finishUpdate(container);
    cleanupTransaction.commit();
}

private Fragment getSubFragmentAtPosition(int position){
    if (subFragments[position] == null){
        subFragments[position] = ...;
    }
    return subFragments[position];
}

}

于 2017-11-21T10:49:47.257 回答
0

我有同样的问题, 只需一次设置两次适配器,仅此而已。

示例代码:

private fun displayImg(photo1:String, photo2:String){
    val pager:ViewPager = v?.findViewById(R.id.ProductImgPager)!!
    val arr = ArrayList<String>()
    arr.add(photo1)
    arr.add(photo2)
    pager.adapter = AdapterImageView(fm, arr ,arr.size)
    pager.adapter = AdapterImageView(fm, arr ,arr.size)

}
于 2020-03-19T20:24:47.947 回答