【问题标题】:FragmentPagerAdapter getItem is not being triggeredFragmentPagerAdapter getItem 没有被触发
【发布时间】:2013-03-23 14:51:28
【问题描述】:

目前,使用FragmentActivity,我使用以下代码在两种类型的片段之间切换。

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

【问题讨论】:

  • 我不喜欢使用 FragmentStatePagerAdapter - 好吧,您至少尝试过它是否有什么不同? 因为在页面之间切换时可能会产生更多开销。 - 什么潜在开销?您发布的带有两个片段的场景非常简单。
  • @Luksprog 紫色和蓝色的 2 个片段用于演示目的。真实案例片段比这更复杂。我知道我可以通过捆绑保存信息或保留实例片段技术来减少一定程度的开销。但是,我意识到为我的情况避免开销的最佳方法是避免使用 FragmentStatePagerAdapter。

标签: android android-fragments android-viewpager fragmentpageradapter


【解决方案1】:

有什么办法可以解决这个问题吗?

我已经下载了您的代码并且出现了问题,因为您没有正确处理那些Fragments。最准确地说,您在基于ViewPagerFragment 中使用嵌套的Fragments 并为此ViewPager 创建适配器,如下所示:

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

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

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

此外,您不应通过构造函数将数据传递给Fragment,因为该数据将无法在配置更改后继续存在,并且会开始出现不良情况。请改用Bundle

【讨论】:

  • 嘿。非常感谢您的大力帮助。但是,我不明白为什么使用 this.getChildFragmentManager 会解决问题。从developer.android.com/reference/android/support/v4/app/… 开始,它通过getSupportFragmentManager() 使用FragmentActivity 的片段管理器(FragmentActivity 是ViewPager 的所有者)。它不使用 ArrayListFragment 的片段管理器(ArrayListFragment(s) 是 ViewPager 的可滑动内容)
  • 在 this.getChildFragmentManager() 中,它返回紫色和蓝色片段的片段管理器。这与官方的例子不同,它使用 ViewPager 的所有者的片段管理器。因此,这让我有些困惑。
  • 我不确定这是否真的回答了我自己的问题。我认为给出的例子是活动中的片段。使用 getFragmentManager 是有意义的。但是,如果对于片段中的嵌套片段,则需要使用 getChildFragmentManager。这是谷歌发布的一些“规则”:developer.android.com/about/versions/…
  • @CheokYanCheng getFragmentManager() 在您的ViewPagerFragment 示例中将从Activity 返回FragmentManager(它基本上是FragmentActivitygetSupportFragmentmanager() 的值,用于添加@987654339 @)。当您使用嵌套片段时,这些片段需要getChildFragmentManager(),因此它们可以附加到父片段。 getFragmentManager()getChildFragmentManagerFragment不是相同的东西(一个返回与片段相关的片段,另一个是用于其嵌套片段的片段管理器)。
  • 如果我能再+1,我会的!非常感谢您的回答和解释!
【解决方案2】:

全球工作测试解决方案。

getSupportFragmentManager() 有时会保留空引用,并且 View pager 不会创建新的片段实例。因为它找到了对同一片段的引用。所以要克服这个使用getChildFragmentManager()以简单的方式解决问题。

不要

new PagerAdapter(getSupportFragmentManager(), fragments);

new PagerAdapter(getChildFragmentManager() , fragments);

【讨论】:

  • 很好的解释。谢谢
【解决方案3】:

简单地使用FragmentStatePagerAdapter 代替FragmentPagerAdapter

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

希望对你有帮助:)

【讨论】:

    【解决方案4】:

    在我的情况下,我正确地调用了

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

    但随后在嵌套片段中,我尝试使用以下方法将容器片段替换为另一个片段:

    getFragmentManager()
    

    你需要去活动并打电话

    getActivity().getSupportFragmentManager();
    

    【讨论】:

      【解决方案5】:

      在我的情况下,将其添加到我的 FragmentPagerAdapter 后它起作用了:

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

      我也像 Luksprog 所说的那样使用了 getChildFragmentManager()

      【讨论】:

        猜你喜欢
        • 2012-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多