ViewPager Fragment动态添加以及动态删除的理解

来源:互联网 发布:java 验证日期格式 编辑:程序博客网 时间:2024/06/07 05:05

       近期在做一个类似于问卷调查答题的一个项目,涉及到Viewpager+Frament的使用,需要使用ViewPager中的Fragement去显示每一道题目,并且可以实现点击上一题和下一题的操作,与一般使用不一样的地方是,每套问卷的题目数量不一样,下一题的跳转是根据当前题的选项去决定,所以Frament的界面数量不能确定,无法事先存放。后来我就采用了进行动态添加Fragment和动态删除Fragment的方式去处理这样的需求,当然之后就遇到很多问题了。。

      

       一开始我想法很简单就是把viewpager当成一般的adapter来做,添加和删除,直接用list的add和remove来操作,之后在adapter.notifyDataSetChanged去更新adapter,结果发现删除没啥问题,但是删除后在添加后,奇怪的是再添加的界面上的数据与之前删除的界面上的数据一样。。而且我调用界面上的控件就会出空指针异常。我第一直觉告诉我是,我没有删除那个界面添加只是调用了原先的那个界面,我就想会不会是viewpager的缓存问题。

      

       之后就开始找网上的资料,搜索关于viewpager的缓存的问题。然后我找到关于viewPager.setOffscreenPageLimit(num);// 设置缓存页面,当前页面的相邻N各页面都会被缓存 ,这个方法setOffscreenPageLimit(num),几经测试过后发现并没有我想要那个效果,就算我设置为0删除添加后也还是会有界面缓存的,结果发现这个方法是用作与预加载时用的,当前如果有5个界面,我设置setOffscreenPageLimit为2当我显示第一个界面的时候,其实我已经在加载了第二第三个界面,但我问题不是预加载出现的问题,就算我不预加载,将值设置为0,那结果就是每切换一个界面就执行当前自己的生命周期,但是其实我那个被删除的界面一直缓存着,这种方式只是重新走了下他的生命周期而已,并没有创建新的Fragment

      

      然后我开始从notifyDataSetChanged这里去找问题,感谢下这位同学分享的http://blog.csdn.net/u013034750/article/details/24323123 也是这篇文章让知道了原来是FragmentManager缓存了界面,必须在instantiateItem()中用FragmentTransaction去remove这个Fragment。


     最后通过这篇文章http://blog.csdn.net/z13759561330/article/details/40737381完美的解决了我的问题,每次在调用instantiateItem的时候我去判断是否最后一个标签页,是否是再次添加的界面,是否已经删除过的界面,达成这些判断的时候我将最后那个界面的Fragment进行替换成list中最后一项的界面。我就直接上代码看啦。。


private class MyPagerFragmentAdapter extends FragmentPagerAdapter {private List<Fragment> fragments;private FragmentManager fm;public MyPagerFragmentAdapter(FragmentManager fm,List<Fragment> fragments) {super(fm);this.fm = fm;this.fragments = fragments;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {Log.i("TAG", "destroyItem___________");super.destroyItem(container, position, object);}@Overridepublic Object instantiateItem(ViewGroup container, int position) {Log.i("TAG", "instantiateItem___________");// 得到缓存的fragmentFragment fragment = (Fragment) super.instantiateItem(container,position);// 得到tag,这点很重要String fragmentTag = fragment.getTag();Log.i("TAG", "替换___________1");if (position == (fragmentList.size() - 1)) {// 是否为最后一页(因为会根据setOffscreenPageLimit的数量执行相应次数)if (isDelete) {// 是否被删除过,删除事件中修改为Trueif (isAdd) {// 是否点击了添加,添加事件中修改为TrueLog.i("TAG", "替换___________2");// 如果这个fragment需要更新FragmentTransaction ft = fm.beginTransaction();// 移除旧的fragmentft.remove(fragment);// 换成新的fragmentfragment = fragments.get(fragmentList.size() - 1);// 添加新fragment时必须用前面获得的tag,这点很重要ft.add(container.getId(), fragment, fragmentTag);ft.attach(fragment);ft.commit();isAdd = false;isDelete = false;}}}return fragment;}@Overridepublic int getItemPosition(Object object) {Log.i("TAG", "getItemPosition___________");return POSITION_NONE;}@Overridepublic Fragment getItem(int arg0) {Log.i("TAG", "getitem___________");return fragments.get(arg0);}@Overridepublic int getCount() {Log.i("TAG", "getCount___________");return fragments.size();}}

      总结:以上是我对Viewpager+Fragment的使用以及遇到的问题的总结,可能不完善,或不专业,望看到此贴的大牛指点,谢谢!

0 0