Viewpager的使用条件
- 多个Fragment滑动切换
- 多个Fragment的展示高度一致
在项目中经常遇到ScrollView嵌套ViewPager的做法,多个Fragment如果高度不一致,却强行使用ViewPager,就需要许多其他兼容代码来完成这个需求,有些得不偿失。
所以不满足这两个条件最好不要使用Viewpager,此外Fragment一旦onAttach到Context,在没有及时清理掉的情况下,会随着Context的生命周期进行数据恢复,这个机制在很多情况下看似无害,不过在实际项目开发过程中会造成许多不必要的内存浪费。
Tips: 刷新界面,需要新建一个新的Fragment,可是FragmentManager会通过反射直接生成一个Fragment保存到内存中
1)不管这个反射生成的实例直接重新创建Fragment就会造成资源浪费,而且在OnCreatView()
如果有异步操作就会带来许多其他问题
2)但如果通过FragmentManager的fragmentManager.findFragmentByTag(name)
查看是否存在Fragment实例的话,再使用该FragmentonAttach
到Context中,那么很多生命周期方法(如OnCreate())也不会再次调用
Viewpager如何添加子View
在看完Viewpager源码之后,产生了一个疑惑:全篇看不到是如何添加子View的,仅仅有方法addNewItem
,难道不需要ViewPager来添加? 随后查看了PagerAdapter的源码。
public abstract class FragmentPagerAdapter extends PagerAdapter {
public abstract Fragment getItem(int position);
@Override
public void startUpdate(ViewGroup container) { }
@Override
public Object instantiateItem(ViewGroup container, int position) {}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {}
@Override
public void finishUpdate(ViewGroup container) {}
@Override
public boolean isViewFromObject(View view, Object object) {}
@Override
public Parcelable saveState() {}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {}
public long getItemId(int position) {}
}
依旧没有addView的踪迹。那还有谁能来管理ViewPager动态地添加View呢?
琢磨了半天,突然想到,还有一种可能性那就是“FragmentManager”,随后我看到了方法moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive)
,看到这我恍然大悟,之前也看了很多网络上的文章对Fragment的源码进行解析,可是对于FragmentManager文章还没有认真地好好了解过,所以导致了对Framgent使用的误解和误用。
现在看来,可以完整地理解ViewPager的机制了:
- 通过ViewPager的setAdapter方法,ViewPager有了一个管理子View工具
PagerAdapter
- PagerAdapter通过实现类的
instantiateItem(ViewGroup container, int position)
方法来创建一个Fragment, - FragmentManager在合适的时机(state==CREATED)调用
container.addView(f.mView)