Fragment与FragmentPagerAdapter的使用
2015-12-14 16:51
549 查看
Fragment与FragmentPagerAdapter的使用
我也是一名刚刚参加工作四个月的小程序猿,写博客只是为了分享一下博主在工作中遇到的一些困难以及难点,如果有什么说错了或者不足的地方,欢迎前辈们指出。博主是做盲人应用的,因为ListView对盲人比较不和谐把。。所以公司一般要程序猿用TabHost内放ViewPager的方式来实现需要的效果。 前两天公司要求做一个咨询2.0的项目,布局风格是外层TabHost,下面有三个Tab,每个Tab对应的是一个FragmentActivity。 博主在写的过程中也遇到了一些困难,现在拿出来跟大家讨论交流下,下面进入正题。
说到Fragment与ViewPager的联合使用就必须得学会联系这两者的Adapter
Fragment的Adapter有两种。一种是FragmentPagerAdapter,另一种是FragmentStatePagerAdapter。从Google官网我们能了解到FragmentPagerAdapter是PagerAdapter中的其中一种实现。它将每一个页面表示为一个 Fragment,并且每一个Fragment都将会保存到fragment manager当中。而且,当用户没可能再次回到页面的时候,fragment manager才会将这个Fragment销毁。那么这样的话,问题就出来了。FragmentPagerAdapter只适合静态的Fragment,因为当该界面不可见时view hierarchy将会被销毁。这样的话会应用程序占用太多资源,所以当页面数量较多时,推荐使用FragmentStatePagerAdapter。
看完Adapter的说明之后,再来说一下博主在工作之中遇到的问题,博主做的是一个资源APP,在另一个界面点击添加后,跳回前一界面时,要同步显示用户订阅的资料。说到这,相信大家也都清楚问题出在哪里了。
问题出在内容刷新这里。首先我们来总结一下问题发生的原因:从官网的文档我们可以得知,FragmentPagerAdapter是会对Fragment做出缓存的。当我们从第二个界面跳回第一个界面时,Activity会执行onResume的方法,而此时我们在Activity的onResume方法中重新加载Fragment并对Adapter进行刷新时,并不会刷新Fragment,而是会去调用FragmentManager中保存的Fragment。
知道问题发生的原因了之后博主在网上看了很多博客,也自己做了一些试验,最后得出了两种可行的方法。
方法1:我们在Adapter中写一个设置Adapter中数据源的方法,并在这个方法中,移除所有FragmentManager中缓存的Fragment,注意此时的提交方法必须使用commitAllowingStateLoss(),如果使用普通的commit()的话可能会报出java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 这个错误,出现这个问题的原因是因为在当Activity变的”容易”被销毁时,系统会自动调用onSaveInstanceState方法。
public void setFragments(ArrayList<Fragment> fragments) { if (this.list != null) { FragmentTransaction ft = fm.beginTransaction(); for (Fragment f : this.list) { ft.remove(f); } ft.commitAllowingStateLoss(); ft = null; fm.executePendingTransactions(); } this.list = fragments; notifyDataSetChanged(); }
方法2:复写父类的instantiateItem的方法。该方法返回的是container所对应的一个Key。
在复写了该方法之后我们首先拿到他缓存中的Fragment,然后在拿到Fragmetn所对应·的Tag。然后我们根据fragmentsUpdateFlag数组中的boolean值来判断该Fragment是否需要更新,如果需要更新则移除掉原来的Fragment并把新的Fragment添加进去。
boolean[] fragmentsUpdateFlag = new boolean[list.size()]; @Override public Object instantiateItem(ViewGroup container, int position) { //得到缓存的fragment Fragment fragment = (Fragment) super.instantiateItem(container, position); //得到tag,这点很重要 String fragmentTag = fragment.getTag(); if (fragmentsUpdateFlag[position % fragmentsUpdateFlag.length]) { //如果这个fragment需要更新 FragmentTransaction ft = fm.beginTransaction(); //移除旧的fragment ft.remove(fragment); //换成 新的fragment fragment = list.get(position % list.size()); //添加新fragment时必须用前面获得的tag,这点很重要 ft.add(container.getId(), fragment, fragmentTag); ft.attach(fragment); ft.commit(); //复位更新标志 fragmentsUpdateFlag[position % fragmentsUpdateFlag.length] = false; } return fragment; }
上面两种方法,第一种是直接粗暴的移除了缓存中所有的Fragment,第二种方法则是根据需要来选择移除,所以一般来说推荐使用第二种方法。
相关文章推荐
- 使用ViewPager实现高仿launcher左右拖动效果
- 灵活使用Android中ActionBar和ViewPager切换页面
- Android 使用 ViewPager循环广告位的实现
- 实现轮转广告带底部指示的自定义ViewPager控件
- 自定义RadioButton和ViewPager实现TabHost带滑动的页卡效果
- Android基于ViewPager Fragment实现选项卡
- 使用ViewPager实现android软件使用向导功能实现步骤
- Android编程ViewPager回弹效果实例分析
- Android 使用ViewPager自动滚动循环轮播效果
- Android ViewPager相册横向移动的实现方法
- Android 使用viewpager实现无限循环(定时+手动)
- Android编程实现ListView头部ViewPager广告轮询图效果
- Android 利用ViewPager实现图片可以左右循环滑动效果附代码下载
- Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法
- viewpager的layout_width="wrap_content"无效问题
- ScrollView ViewPager嵌套导致滑动冲突解决方案
- Fragment+viewpager+Fragment 嵌套 第二次进入该fragment不显示数据
- android自定义tabbar,并带badgeview消息提示
- ViewPager播放图片问题
- CollapsingAvatarToolbar 头像随ListView滚动缩回到ActionBar特