ViewPager的懒加载思路

本文探讨了在Android开发中如何解决ViewPager预加载导致的流量消耗和性能问题。通过分析ViewPager源码,尝试修改默认预加载页面数以及在数据加载过程中优化,避免不必要的数据请求。文章提供了两种方法,包括自定义ViewPager和利用页面监听器动态加载数据。

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

转载请注明出处:http://blog.youkuaiyun.com/xiong199208/article/details/52725793


在android开发中,ViewPager不仅仅是当成简单的轮播图使用,很多时候都用来搭建框架.

这里写图片描述

在这个页面中,就是两个ViewPager的嵌套,新闻中心是外部ViewPager的一个页面,其内容又是一个ViewPager.
这时候我们就要面对一个问题,ViewPager默认是会预加载的,在这个需求下,预加载会耗费用户非常多的流量,在数据请求过程中,也会造成耗时过多,影响用户体验,所以我们需要禁止掉预加载,在这里介绍两个方法.

  • 在ViewPager源代码上想办法
  • 在数据加载过程中找思路

1.ViewPager源代码上的思路

首先我们需要关注ViewPager这样一个方法:

mViewPager.setOffscreenPageLimit(0);

这实际上是控制预加载页面个数的方法,具体实现源码为:

public void setOffscreenPageLimit(int limit) {
        if (limit < DEFAULT_OFFSCREEN_PAGES) {
            Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
                    + DEFAULT_OFFSCREEN_PAGES);
            limit = DEFAULT_OFFSCREEN_PAGES;
        }
        if (limit != mOffscreenPageLimit) {
            mOffscreenPageLimit = limit;
            populate();
        }
    }

是不是我们只要传0进去,就能阻止预加载了?很遗憾,并不行,从源码上可以看出,我们传入一个期望值,会与默认的DEFAULT_OFFSCREEN_PAGES进行比较,如果小于默认值,则会取默认值,而默认的值为1,也就是说,不管传入的值多小,都会左右预加载至少一个页面。
这时候我们就要思考,如何才能改变这个默认值呢,找遍了源码,并没有能操作这个默认值的方法,那我们只能来硬的了,直接找到ViewPager.java文件,修改内容,成为自己的ViewPager.
这里写图片描述

改完后就可以使用了:

<com.itheima.lazyviewpager.view.LayzyViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </com.itheima.lazyviewpager.view.LayzyViewPager>

打完收工!


2.在数据加载过程上寻找思路

第一种方法简单,一劳永逸,然而组长找到你:熊孩子!代码没写几行,一下就增加了100kb的无用代码!
好吧,简便方法不能用了,老老实实寻找其他突破口吧。我们需要取消预加载,其实是为了让ViewPager当前页之外的地方,别乱找trouble,也就是加载页面可以,别发起数据请求,有了思路,代码怎么实现呢?具体实现方法是:

  • 维护一个集合,将已经加载的页面存入集合中
  • 调用ViewPager的addOnPageChangeListener监听,显示哪个页面,再加载哪个页面的数据,此时就能将集合中的对象取出来使用。
  • 注意一个细节,ViewPager在显示首页时,不会调用onPageSelected,需要在onPageScrolled进行手动调用。
public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {

    private ViewPager mPager;

    public String[] title = {"fragment01","fragment02","fragment03","fragment04"};
    //维护一个已经加载了的Fragment集合
    List<BaseFragment> mFragments = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPager = (ViewPager) findViewById(R.id.viewpager);
        //ViewPager的指示器,用的是开源框架,为了方便测试- -;
        TabIndicator indicator = (TabIndicator) findViewById(R.id.indicator);


        mPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
        //指示器绑定ViewPager
        indicator.setViewPager(mPager);

        //设置ViewPager监听,显示出当前页时,再加载数据
        mPager.addOnPageChangeListener(this);

    }

    Boolean first = true;

   //显示首页时,onPageSelected不会被调用,需要手动调用它
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (first && positionOffset == 0 && positionOffsetPixels == 0){
            onPageSelected(0);
            first = false;
        }
    }

    @Override
    public void onPageSelected(int position) {

        BaseFragment fragment = mFragments.get(position);
        //加载数据
        fragment.loadData();
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

    /**
     * ViewPager的适配器
     */
    class MyPagerAdapter extends FragmentPagerAdapter{

        @Override
        public CharSequence getPageTitle(int position) {
            return title[position];
        }

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {

            //将已加载的fragment用集合存起来
            switch (position) {
                case 0:
                    BaseFragment fragment01 = new Fragment01();
                    mFragments.add(fragment01);
                    return fragment01;

                case 1:
                    BaseFragment fragment02 = new Fragment02();
                    mFragments.add(fragment02);
                    return fragment02;

                case 2:
                    BaseFragment fragment03 = new Fragment03();
                    mFragments.add(fragment03);
                    return fragment03;

                case 3:
                    BaseFragment fragment04 = new Fragment04();
                    mFragments.add(fragment04);
                    return fragment04;

                default:
                    BaseFragment fragment = new Fragment01();
                    mFragments.add(fragment);
                    return fragment;

            }
        }

        @Override
        public int getCount() {
            return 4;
        }
    }
}

具体的demo可以在这里看到:
https://github.com/xiong199208/LayzyViewPager

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值