正确插入和删除视图到浏览器

我正在用viewpager和碎片做一个adroid应用程序。 我想做一个选项来dynamic地添加或删除分页到分页器。 我有一个自定义的FragmentPagerAdapter:

public class MyAdapter extends FragmentPagerAdapter implements TitleProvider{ protected final List<PageFragment> fragments; /** * @param fm * @param fragments */ public MyAdapter(FragmentManager fm, List<PageFragment> fragments) { super(fm); this.fragments = fragments; } public void addItem(PageFragment f){ fragments.add(f); notifyDataSetChanged(); } public void addItem(int pos, PageFragment f){ for(int i=0;i<fragments.size();i++){ if(i>=pos){ getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag(getFragmentTag(i))).commit(); } } fragments.add(pos,f); notifyDataSetChanged(); pager.setAdapter(this); pager.setCurrentItem(pos); } public void removeItem(int pos){ getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag(getFragmentTag(pos))).commit(); for(int i=0;i<fragments.size();i++){ if(i>pos){ getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag(getFragmentTag(i))).commit(); } } fragments.remove(pos); notifyDataSetChanged(); pager.setAdapter(this); if(pos<fragments.size()){ pager.setCurrentItem(pos); }else{ pager.setCurrentItem(pos-1); } } @Override public Fragment getItem(int position) { return fragments.get(position).toFragment(); } @Override public int getCount() { return fragments.size(); } @Override public int getItemPosition(Object object) { return POSITION_NONE; } private String getFragmentTag(int pos){ return "android:switcher:"+R.id.pager+":"+pos; } public String getTitle(int position) { String name = fragments.get(position).getName(); if(name.equals("")) return "- "+position+" -"; return name; } } 

我可以删除除0之外的任何片段,当我尝试删除它时notifyDataSetChanged();我得到一个NullPointerExceptionexception; 或在pager.setAdapter(this); 如果我注释通知。

当我尝试插入新页面时,我也遇到了NullPointerException。 当我将新的页面添加到列表的末尾,它工作正常。 我甚至尝试读取插入片段后,这些片段.add(pos,f)

  for(int i=0;i<fragments.size();i++){ if(i>=pos){ getSupportFragmentManager().beginTransaction().add(fragments.get(i).toFragment(),getFragmentTag(i-1)).commit(); } } 

如果我使用getFragmentTag(i-1)我又得到了空指针。 只使用i我得到了非法状态,因为不能修改片段的标签。 使用beginTransaction().add(pager.getId,fragments.get(i).toFragment())它仍然是空指针…

我的问题是:我做错了什么,怎样才能正确地做? (也许:从何处notyfyDataSetChanged()获取数据时导致nullpointerexception?)

Solutions Collecting From Web of "正确插入和删除视图到浏览器"

这是我用来解决实例化时被标记为碎片的问题,以及在尝试添加或删除页面时,以前标记的碎片无法在ViewPager中更改位置的事实,即得到exception:

java.lang.IllegalStateException:无法更改片段的标签MyFragment {4055f558 id = 0x7f050034 android:switcher:2131034164:3}:was android:switcher:2131034164:3 now android:switcher:2131034164:4

此适配器是使用预先列出的所有页面创build的,然后可以使用setEnabled(int position,boolean enabled)来禁用或启用在ViewPager中隐藏或显示这些页面的某些页面。

它通过维护所有片段的内部列表,但暴露给ViewPager并仅映射启用片段的位置。

 public class DynamicFragmentPagerAdapter extends FragmentPagerAdapter { public final ArrayList<Fragment> screens = new ArrayList<Fragment>(); private Context context; private List<AtomicBoolean> flags = new ArrayList<AtomicBoolean>(); public DynamicFragmentPagerAdapter(FragmentManager fm, Context context, List<Class<?>> screens) { super(fm); this.context = context; for(Class<?> screen : screens) addScreen(screen, null); notifyDataSetChanged(); } public DynamicFragmentPagerAdapter(FragmentManager fm, Context context, Map<Class<?>, Bundle> screens) { super(fm); this.context = context; for(Class<?> screen : screens.keySet()) addScreen(screen, screens.get(screen)); notifyDataSetChanged(); } private void addScreen(Class<?> clazz, Bundle args) { screens.add(Fragment.instantiate(context, clazz.getName(), args)); flags.add(new AtomicBoolean(true)); } public boolean isEnabled(int position) { return flags.get(position).get(); } public void setEnabled(int position, boolean enabled) { AtomicBoolean flag = flags.get(position); if(flag.get() != enabled) { flag.set(enabled); notifyDataSetChanged(); } } @Override public int getCount() { int n = 0; for(AtomicBoolean flag : flags) { if(flag.get()) n++; } return n; } @Override public Fragment getItem(int position) { return screens.get(position); } @Override public int getItemPosition(Object object) { return POSITION_NONE; // To make notifyDataSetChanged() do something } @Override public void notifyDataSetChanged() { try { super.notifyDataSetChanged(); } catch (Exception e) { Log.w("", e); } } private List<Fragment> getEnabledScreens() { List<Fragment> res = new ArrayList<Fragment>(); for(int n = 0; n < screens.size(); n++) { if(flags.get(n).get()) res.add(screens.get(n)); } return res; } @Override public Object instantiateItem(ViewGroup container, int position) { // We map the requested position to the position as per our screens array list Fragment fragment = getEnabledScreens().get(position); int internalPosition = screens.indexOf(fragment); return super.instantiateItem(container, internalPosition); } @Override public CharSequence getPageTitle(int position) { Fragment fragment = getEnabledScreens().get(position); if(fragment instanceof TitledFragment) return ((TitledFragment)fragment).getTitle(context); return super.getPageTitle(position); } public static interface TitledFragment { public String getTitle(Context context); } } 

我有一个解决scheme,适用于基于非片段的适配器。 看看我的post ,看看是否有帮助。

我可以删除除0之外的任何片段。

对我来说,如果只使用removeItem的for循环中的条件,

  if (i >= pos){ fm.beginTransaction().remove(fragments.get(i).getFragment()).commit(); }