我也刚刚在我们的项目中遇到了这个问题。根本原因是 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];
}
}