转载请注明出处: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