深入理解ViewPager

本文解析了Viewpager的工作原理及使用条件,包括其与Fragment的配合机制,并探讨了不当使用可能带来的内存浪费问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Viewpager的使用条件

  1. 多个Fragment滑动切换
  2. 多个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的机制了:

  1. 通过ViewPager的setAdapter方法,ViewPager有了一个管理子View工具PagerAdapter
  2. PagerAdapter通过实现类的instantiateItem(ViewGroup container, int position)方法来创建一个Fragment,
  3. FragmentManager在合适的时机(state==CREATED)调用container.addView(f.mView)

转载于:https://my.oschina.net/u/1011897/blog/1510652

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值