我正在使用来自ViewPageIndicator的ViewPager,我需要能够在其他片段的中间动态插入一个片段。
我尝试使用FragmentPagerAdapter和FragmentStatePagerAdapter(都来自v4支持代码)来管理模型,第一个似乎无论如何都不会管理页面的插入。 而且只有第二个在我进行了一个天真的getItemPosition实现并始终返回POSITION_NONE时才有效,但这会导致每次我滑动时完全重新创建页面。
我观察到FragmentStatePagerAdapter(FSP)存在的问题是:
我尝试使用FragmentPagerAdapter和FragmentStatePagerAdapter(都来自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。
condition
为真,是否有三个项?如果是的话,那可能是通知方面出了问题。有趣的问题… - Michał Klimczak