Fragment与FragmentPagerAdapter的使用
来源:互联网 发布:java迭代器怎么写 编辑:程序博客网 时间:2024/05/16 17:07
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,第二种方法则是根据需要来选择移除,所以一般来说推荐使用第二种方法。
- Fragment与FragmentPagerAdapter的使用
- TabLayout与ViewPager和Fragment、FragmentPagerAdapter的配合使用
- 【Fragment使用】(一)FragmentPagerAdapter与FragmentStatePagerAdapter区别
- Fragment与Viewpager及FragmentPagerAdapter
- FragmentActivity、Fragment、FragmentPagerAdapter与FragmentManager
- fragment+viewpager+FragmentPagerAdapter使用随记
- 小结Fragment与FragmentPagerAdapter的生命周期及其关系
- TabLayout与ViewPager和Fragment、FragmentPagerAdapter的合用
- TabLayout与ViewPager和Fragment、FragmentPagerAdapter的合用
- Fragment内嵌套使用FragmentPagerAdapter出现空白页的问题
- ViewPager 如何得到当前的Fragment (使用FragmentPagerAdapter)
- ViewPager 如何得到当前的Fragment (使用FragmentPagerAdapter)
- ViewPager 如何得到当前的Fragment (使用FragmentPagerAdapter)
- (转)ViewPager 如何得到当前的Fragment (使用FragmentPagerAdapter)
- FragmentPagerAdapter+fragment错位的问题解决
- Android Fragment两种适配FragmentPagerAdapter与FragmentStatePagerAdapter
- 正确使用FragmentPagerAdapter,避免Fragment重叠问题
- ViewPager + FragmentPagerAdapter的使用
- 第十六周项目1-直接选择排序
- 第十六周 项目1.3- 验证算法
- 第十六周--大数据集上排序算法性能的体验
- 第十四周 折半查找
- 第十三周项目5
- Fragment与FragmentPagerAdapter的使用
- mysql主从切换步骤
- 第12周项目3图遍历算法的实现
- Spring的“零配置”支持,用annotation替代xml
- 8086的寻址方式
- iOS恢复固件的方法
- 双边滤波器的原理及实现
- 第15周项目1-验证算法
- 聚类