在FragmentPageAdapter中插入页面到中间位置

15
我正在使用来自ViewPageIndicator的ViewPager,我需要能够在其他片段的中间动态插入一个片段。
我尝试使用FragmentPagerAdapterFragmentStatePagerAdapter(都来自v4支持代码)来管理模型,第一个似乎无论如何都不会管理页面的插入。 而且只有第二个在我进行了一个天真的getItemPosition实现并始终返回POSITION_NONE时才有效,但这会导致每次我滑动时完全重新创建页面。
我观察到FragmentStatePagerAdapter(FSP)存在的问题是:
  • 我从两个页面 [A] [B] 开始
  • 然后我在中间插入 [C] [A] [C] [B]。插入后,我调用 notifyDataSetchange()
  • 然后 FSP 调用 [A] 的 getItemPosition 并得到 0
  • 然后 FSP 调用 [B] 的 geTItemPosition 并得到 2。然后它说...哦,我必须销毁 [B] 并将 mFragments.set(2, null),然后由于 mFragments 数组只有两个元素,所以抛出 IndexOutOfBoundsException

看了一下代码,似乎提供的 FragmentStatePagerAdapter 不支持在中间插入。这是正确的吗?还是我漏掉了什么?

更新: 适配器中的插入是以逻辑方式进行的,当某个条件为真时,页面会增加一个。在 getItem() 中使用构造函数创建片段,如下所示:

void setCondition(boolean condition) {
   this.condition=condition;
   notifyDataSetChanged();
}
public int getCount(){
    return condition?3:2;
}
public Fragment getItem(int position) {
    if(position==0) 
        return new A();
    else if(position==1)
        return condition?new C():new B();
    else if(position==2 && condition)
        return new B();
    else throw new RuntimeException("Not expected");
}
public int getItemPosition(Object object) {
    if(object instanceof A) return 0;
    else if(object instanceof B) return condition?2:1;
    else if(object instanceof C) return 1;
} 

解决方案:

正如接受的答案所述,关键是实现 getItemId() 方法。

请确保使用至少 2012年6月版本的android-support库。因为该方法是在此版本中添加的。在此版本之前,该方法不存在,适配器无法正确管理插入。 还要确保使用 FragmentPageAdapter,因为 FragmentStatePagerAdapter 仍然不起作用,因为它不使用 ids。


“插入”是什么意思?您如何在PagerAdapter中实例化Fragments?像这样:http://www.androiddesignpatterns.com/2012/05/using-newinstance-to-instantiate.html?或者只需发布适配器的代码和插入方式即可。 - Michał Klimczak
我使用构造函数创建它们。我已经更新了问题并提供了更多信息。 - lujop
你有没有检查 ViewPager 在 Adapter(Activity)创建时,如果 condition 为真,是否有三个项?如果是的话,那可能是通知方面出了问题。有趣的问题… - Michał Klimczak
1个回答

5
你忘记了一个方法。
覆盖FragmentPagerAdapter中的getItemId(int position),它只返回位置,而应该返回能够标识片段实例的内容。
public long getItemId(int position) {
    switch (position) {
    case 0:
        return 0xA;
    case 1:
        return condition ? 0xC : 0xB;
    case 2:
        if (condition) {
            return 0xB;
        }
    default:
        throw new IllegalStateException("Position out of bounds");
    }
}

我对此有些困惑。我正在使用支持库的第8个版本进行工作。而你提到的方法出现在R9(2012年6月)中http://developer.android.com/tools/extras/support-library.html。 在新版本中,FragmentPagerAdapter使用它并且可以正常工作。FragmentStatePagerAdapter似乎没有使用它,仍然无法正常工作。 - lujop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接