viewpager布局复用中FragmentPagerAdapter的坑,源码分析,控件id的一些思考
来源:互联网 发布:石家庄手机数据恢复 编辑:程序博客网 时间:2024/06/01 09:31
一个fragment的布局复用,里面是tablayout+viewpager,viewpager加载不同adapter,adapter继承FragmentPageAdapter。运行后有问题,先初始化的fragment正常显示,后加载的fragment里的viewpager全部是空白,这就很尴尬了,第一反应是fragment没add进FragmentManager,因为在同一个activity里,所以只有一个FragmentManager,debug一下。
List<Fragment> fragments = getSupportFragmentManager().getFragments();
果然第二个viewpager里的fragment一个都没add,继续查问题。FragmentPageAdapter是通过getItem(position)获取fragment对象的,并且已初始化过得fragment不会再次调用,会从FragmentManager中取出来,debug发现第二个getItem并未被调用,问题很明显,FragmentPageAdapter认为对应position的fragment已经初始化过了,不重新调用,好吧,查源码吧。
@Override public Object instantiateItem(ViewGroup container, int position) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } final long itemId = getItemId(position); // Do we already have this fragment? String name = makeFragmentName(container.getId(), itemId); Fragment fragment = mFragmentManager.findFragmentByTag(name); if (fragment != null) { if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment); mCurTransaction.attach(fragment); } else { fragment = getItem(position); if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment); mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId)); } if (fragment != mCurrentPrimaryItem) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } return fragment; }private static String makeFragmentName(int viewId, long id) { return "android:switcher:" + viewId + ":" + id; }
FragmentPageAdapter 继承自PageAdapter,实现了instantiateItem方法,返回fragment对象。通过findFragmentByTag查找fragment,如果存在就不调用getItem方法,于是关键就在于container.getId(),这个container其实就是我们的viewpager,打印viewpager.getId()
07-24 21:55:21.605 7796-7796/cf.movie.slmovie E/viewPage: movie>>>>>213155854307-24 21:55:21.640 7796-7796/cf.movie.slmovie E/viewPage: tv>>>>>2131558543
果然没错,id是一样的,所以FragmentPageAdapter 不会重新调用getItem,这还没完,怎么办呢,布局copy一份,单独用,还是没用。好吧,viewpage的id改了一下,ok。
控件id的一些思考:
我们都知道每个view,layout系统都会分配一个id,保存在R文件里,一一对应,使用的时候view.findViewById()去找对应的组件,这个id的生成机制没找到。但是我们自己给view设置了一个id,项目庞大的时候,我们设置的这个id可能会有重复的,但是我们同一个view,同一个layout中的id不会重复,所以不用担心重名的问题。
查找R文件发现同名的view只会生成一个id。
public static final int viewPage=0x7f0d0090;
回到本问题中,fragment添加的tag代码如下
"android:switcher:" + viewId + ":" + id;
viewId不同,才能标识不同的fragment,但是即使加上view.getParent()的id,依然无法保证他的唯一性,因为嵌套层数可能非常多。
不知道这个类设计的时候出于什么考虑设计成这样,应该留一个方法去处理设置tag比较好一点。
于是尝试重写instantiateItem方法,添加标识
@Override public Object instantiateItem(ViewGroup container, int position) { FragmentTransaction mCurTransaction = fm.beginTransaction(); final long itemId = getItemId(position); // Do we already have this fragment? String name = makeFragmentName(which.toString(), container.getId(), itemId); Fragment fragment = fm.findFragmentByTag(name); if (fragment != null) { mCurTransaction.attach(fragment).commitAllowingStateLoss(); } else { fragment = getItem(position); mCurTransaction.add(container.getId(), fragment, makeFragmentName(which.toString(), container.getId(), itemId)).commitAllowingStateLoss(); } if (fragment != getItem(position - 1)) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } String tag = fragment.getTag(); LogUtils.e("viewPager", "tag>>>>>" + tag); return fragment; } private static String makeFragmentName(String className, int viewId, long id) { return className + "android:switcher:" + viewId + ":" + id; }
事实证明,没用,但是FragmentManager中有正确的fragment,但是就是不行,症状一样,继续翻源码,只找到FragmentPageAdapter 中的一段注释
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.
可能对valid ID理解不同, 相同的ID不是有效的ID吗,一定要unique?
- viewpager布局复用中FragmentPagerAdapter的坑,源码分析,控件id的一些思考
- ViewPager + FragmentPagerAdapter的使用
- ViewPager+FragmentPagerAdapter的使用
- 源码分析FragmentPagerAdapter和FragmentStatePagerAdapter的区别
- 深入探讨ViewPager的FragmentPagerAdapter
- android的ViewPager+FragmentPagerAdapter实现
- 清除ViewPager+FragmentPagerAdapter的缓存
- ViewPager +FragmentPagerAdapter 的获取getActivity()
- Fragment嵌套带来的坑--页面点击无反应(顺带ViewPager之 FragmentPagerAdapter简单分析)
- ViewPager+FragmentPagerAdapter跟ViewPager+FragmentStatePagerAdapter的区别
- viewpager + fragmentpageradapter 切换fragment产生的问题
- ViewPager+FragmentPagerAdapter的选项卡切换
- 数据分析的一些思考
- ViewPager中动态添加XML布局文件,并获取XML文件中控件ID的操作(inflate)
- android 布局控件id的+号
- ViewPager-------Fragment作为ViewPager的数据源(FragmentPagerAdapter)
- FragmentPagerAdapter 的那些坑
- MapReduce源码分析之Task中关于对应TaskAttempt存储Map方案的一些思考
- SpringMVC札集(01)——SpringMVC入门完整详细示例(上)
- 【宏观】长期中的通货膨胀与货币
- Activity的4种启动模式
- 输入框延时调接口(防止不停调用)
- js怎么让浏览器自动全屏显示
- viewpager布局复用中FragmentPagerAdapter的坑,源码分析,控件id的一些思考
- AtomicInteger源码分析
- promise的用法
- 使用Git上传项目代码到github
- 大数据分布式集群搭建(7)
- 浅谈标准I/O缓冲区
- css居中补充
- builder设计模式学习笔记
- ios 简单的本地json格式文件解析