【Android】开发小记——ViewPager的几种适配器

最近需要做标签页,虽然ViewPager已经是多年前的产物,后续已经有ViewPager2功能更为强大,不过只是做简单常规的标签页ViewPager也还是挺方便的,就顺便学习下。

1.PagerAdapter

介绍:ViewPager支持的适配器基类,如果只是展示简单的视图内容推荐使用,主要重写四个方法:

// 页面个数

int getCount()

// 用于比对当前视图和对应的页面实体是否一致,页面实体不一定是View,可以是Fragment甚至binding等,总之能提供View的都行,按需要来,当然如果是Fragment的话,最好不要直接用PagerAdapter,毕竟后面有针对的封装适配器

boolean isViewFromObject(View view, Object object)

// 根据索引添加对应的试图到容器中,才能正常显示,因为每个标签页对应的不一定是View,所以返回的是Object

Object instantiateItem(ViewGroup container, int position)

// 当ViewPager判断某个试图需要destory的时候(具体什么时候可以自定义配置)执行的操作

void destroyItem(ViewGroup container, int position, Object object)

以上就是简单的使用方式,最常规的写法就是在Adapter的构造函数加参数,把需要显示的View合集传入,然后进行显示和移除等,如下:

public class MainViewPagerAdapter extends PagerAdapter {
    /**
     * View合集
     */
    private List<View> pagerList;

    /**
     * 构造函数
     * @param pagerList View合集
     */
    public MainViewPagerAdapter(List<View> pagerList) {
        this.pagerList = pagerList;
    }

    /**
     * 总的个数
     * @return
     */
    @Override
    public int getCount() {
        return this.pagerList.size();
    }

    /**
     * 进行比对
     * @param view
     * @param object
     * @return
     */
    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view == object;
    }

    /**
     * 构造View
     * @param container
     * @param position
     * @return
     */
    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        container.addView(pagerList.get(position));
        return pagerList.get(position);
    }

    /**
     * 清除布局
     * @param container
     * @param position
     * @param object
     */
    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        container.removeView(pagerList.get(position));
    }
}

针对视图的移除多说一句,PagerAdapter默认是预加载和保留一个视图,左右各一个,假如当前正在显示标签页3视图View3,View2还保留在内存中,同时预先加载View4,而View1将会被移除,缓存的页数可以通过:

setOffscreenPageLimit(int limit)

来配置。

2.FragmentPagerAdapter

介绍:针对ViewPager的标签页为Fragment的情况封装的适配器,继承了PagerAdapter,主要重写三个方法:

// 标签页个数

int getCount()

// 获取标签页对应的Fragment

Fragment getItem()

// 适配器中针对Fragment进行了生命周期的管理,所以需要传入FragmentManager,哪怕你在外面构建好了Fragment传入,behavior有效的参数FragmentPagerAdapter的静态常量:BEHAVIOR_SET_USER_VISIBLE_HINT 和 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT

构造函数(FragmentManager fm, int behavior)

主要讲讲这个类针对Fragment做了什么优化:

1.PagerAdapter烦人的instantiateItem帮你写了,你只需要在getItem中返回需要显示Fragment对象即可,添加视图、使用FragmentManager开事务的操作都在FragmentPagerAdapter中帮你处理了(构造函数要求传入FragmentManager的原因之一),同样的,对不可见Fragment的操作也帮你做了处理;

2.因为Fragment具有生命周期,同时一般占用内存也较大(相比单纯的View),针对Fragment的复用、销毁做了特殊的处理:

a)预加载的Fragment(默认左右各一个标签页)会执行Fragment的生命周期到onStart();

b)当前显示的时候执行onResume;

c)不可见但是保留在内存中的视图,执行onPause();

d)不可见而且超出缓存范围需要销毁的,执行到onDestroyView() (注意,不执行onDestroy(),只是销毁了视图而已,因此如果标签页特别多、每个fragment又特别大的时候,谨慎考虑),以下是打印的生命周期日志:

贴上示例的代码(因为fragment生命周期都是Adapter处理,因此完全可以先把Fragment实例构建好了传入,只要在Fragment的构造函数里不会初始化和加载太多东西,一般也不应该这么做):

public class MainViewPagerFragmentAdapter extends FragmentPagerAdapter {
    /**
     * Fragment合集
     */
    private List<Fragment> fragmentList;

    /**
     * 传入Fragment合集
     * @param fragmentList
     */
    public void setFragmentList(List<Fragment> fragmentList) {
        this.fragmentList = fragmentList;
    }

    public MainViewPagerFragmentAdapter(@NonNull FragmentManager fm, int behavior) {
        super(fm, behavior);
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        return fragmentList.get(position);
    }

    @Override
    public int getCount() {
        return fragmentList.size();
    }
}

3.FragmentStatePagerAdapter

介绍:很类似FragmentPagerAdapter的另一个适配器,继承了PagerAdapter,使用方法几乎没有什么不同,唯一的不同点在于标签页不在缓存区间需要销毁的时候,FragmentPagerAdapter只走onDestroyView(),而FragmentStatePagerAdapter会执行完onDestroy()也就是完全销毁,不过销毁的同时会保存Fragment的数据SavedState,后面重新创建Fragment的时候会进行恢复(和系统内存不足时候回收一样,默认只会保存界面View的一些必要元素,如果需要保存变量等更多内容,fragment中需要做对应的处理),以下是对应的生命周期:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值