35

当前,使用FragmentActivity,我使用以下代码在2种片段之间切换。FragmentPagerAdapter getItem未被触发

private void toggle() { 
    Fragment oldFragment = getSupportFragmentManager().findFragmentById(R.id.content); 
    Fragment fragment = null; 
    if (oldFragment instanceof ColorFragment) { 
     fragment = new ViewPagerFragment(); 
    } else { 
     fragment = new ColorFragment(android.R.color.black); 
    } 

    getSupportFragmentManager().beginTransaction().replace(R.id.content, fragment).commitAllowingStateLoss(); 
} 

2片段正在切换。

  • ColorFragment - 一个简单的片段,用纯黑色填充背景。
  • ViewPagerFragment - 片段包含ViewPager。用户可以在紫色片段和蓝色片段之间滑动。

负责划动紫色和蓝色碎片的代码如下。

private static class MyFragmentPagerAdapter extends FragmentPagerAdapter { 

    public MyFragmentPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

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

    @Override 
    public Fragment getItem(int position) { 
     switch (position) { 
     case 0: 
      return new ColorFragment(android.R.color.holo_purple); 
     default: 
      return new ColorFragment(android.R.color.holo_blue_bright); 
     } 
    }  
} 

但是,我在切换过程中遇到了奇怪的行为。

  1. 显示黑色片段。
  2. 切换。
  3. 查看传呼机,它可以在显示的紫色和蓝色碎片之间滑动。
  4. 切换。
  5. 显示黑色片段。
  6. 切换。
  7. 没有显示,因为MyFragmentPagerAdapter的getItem没有被触发。

我觉得我的情况是类似FragmentPagerAdapter getItem is not called

然而,页面之间切换时,我不喜欢使用FragmentStatePagerAdapter,因为潜在更大的开销成本。

解决此问题的任何解决方法?

我有一个完整的可行的源代码来说明此问题:https://www.dropbox.com/s/jok9tz5ktvfcteo/viewpagerbug.zip

+0

*我不喜欢使用FragmentStatePagerAdapter * - 嗯,你是否至少试图看看它是否有任何分歧? *因为在页面之间切换时潜在的更多开销的成本。* - 可能的开销是多少?你用两个片段发布的场景很简单。 – Luksprog 2013-03-23 14:59:37

+0

@Luksprog 2个紫色和蓝色的颜色片段用于演示目的。真实案例片段比这更复杂。我知道我可以通过捆绑保存信息或保留实例片段技术来减少某些开销的扩展。然而,我认识到避免我的情况开销的最好方法是避免使用FragmentStatePagerAdapter。 – 2013-03-23 15:30:32

回答

101

任何变通方法来解决这个问题?

我已经下载了你的代码,出现这个问题,因为你没有处理那些Fragments的权利。大多数正是你在ViewPager基于Fragment使用嵌套Fragments并为ViewPager您创建适配器这样的:

MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(this.getFragmentManager()); 

相反,你应该使用getChildFragmentManager()绑定嵌套的片段:

MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(this.getChildFragmentManager()); 

而且,您不应该通过构造函数将数据传递到Fragment,因为数据在配置更改后无法存活,并且会出现不好的情况。改为使用Bundle

+1

嘿。真的非常感谢你的帮助。但是,我不明白为什么使用this.getChildFragmentManager将解决问题。从http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html,它通过getSupportFragmentManager()(FragmentActivity是ViewPager的所有者)使用FragmentActivity的片段管理器。它不使用ArrayListFragment的片段管理器(ArrayListFragment(s)是ViewPager的可滑动内容) – 2013-03-23 16:26:00

+0

在this.getChildFragmentManager()中,它返回片段管理器的紫色和蓝色片段。这与正在使用ViewPager所有者的片段管理器的官方示例不同。因此,这让我感到困惑。 – 2013-03-23 16:28:46

+1

我不确定这是否真的回答了我自己的问题。我认为给出的例子是活动中的片段。使用getFragmentManager是有道理的。但是,如果对于片段内的嵌套片段,则需要使用getChildFragmentManager。这是Google发布的一个“规则”:http://developer.android.com/about/versions/android-4.2.html#NestedFragments – 2013-03-23 16:48:55

12

全球工作测试解决方案。

getSupportFragmentManager()保留空引用一些时间和查看寻呼机不创建新的片段实例。因为它找到对同一片段的引用。所以过来这个用简单的方法解决问题。

不要

new PagerAdapter(getSupportFragmentManager(), fragments);

new PagerAdapter(getChildFragmentManager() , fragments);

+0

很好的解释。谢谢 – 2015-09-01 19:43:39

0

在我来说,我是正确调用

MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(this.getChildFragmentManager()); 

但随后在嵌套的片段,我尝试使用,以取代另一个容器片段:

getFragmentManager() 

你需要去的活动,并呼吁

getActivity().getSupportFragmentManager(); 
0

在我的情况下工作后,将其添加到我的FragmentPagerAdapter

@Override 
    public int getItemPosition(Object object) { 
     return POSITION_NONE; 
    } 

,我也用getChildFragmentManager()像Luksprog说的

0

简单使用FragmentStatePagerAdapter代替FragmentPagerAdapter

可以使用new MyFragmentPagerAdapter(this.getChildFragmentManager())

希望它会帮助你:)