ViewPager详解填充Fragment和懒加载
Posted 万合天宜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ViewPager详解填充Fragment和懒加载相关的知识,希望对你有一定的参考价值。
ViewPager详解(三)Fragment的填充和懒加载实现
效果图
一、ViewPager基础学习请上传送门
ViewPager详解(一)简单介绍和使用
ViewPager详解(二)广告轮播图
ViewPager详解(三)引导页
二、使用Fragment来填充ViewPager
实际开发当中,TabLayout+ViewPager+Fragmenet是使用非常多的控件组合。这里主要介绍ViewPager和Fragment的联合使用,TabLayout使用非常简单,这里也简单介绍一下。
2.1 TabLayout组件的简单介绍
- TabLayout是Material Design组件开发中的一种,使用时需要先导入design库的依赖。
TabLayout做出的效果是一排可以滑动的Tab,相当于一排指示器。
在布局中申明控件
<android.support.design.widget.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabBackground="@color/colorPrimary" app:tabIndicatorColor="@color/colorAccent" app:tabMode="scrollable" app:tabTextColor="@android:color/white" app:tabSelectedTextColor="@color/colorAccent"/>
基本属性介绍,布局和代码都可以使用
- tabBackground:背景颜色
- tabIndicatorColor:指示器颜色,横线
- tabMode:模式,有scrollable和fixed两种,分别表示可以滑动和固定的意思
- tabTextColor:正常文字颜色
- tabSelectedTextColor:选中文字颜色
- tabIndicatorHeight:指示器高度
- tabPadding:指示器内边距
代码中绑定ViewPager
- 在ViewPager设置Adapter之后,调用tabLayout的setupWithViewPager方法绑定ViewPager
- 设置显示的内容
- 可以调用tabLayout的addTab方法添加
- 也可以重写ViewPager适配器的getPagerTitle方法返回显示的内容
2.2 获取ViewPager对象,设置Fragment的适配器,默认继承FragmentPagerAdapter
需要重写的方法
- FragmentAdapter(FragmentManager fm):构造方法,需要传入Fragment管理器,getSupportFragmentManager()兼容的管理器
- getCount():返回显示的条目数量
- getItem():返回position位置的Fragment对象
创建BaseFragment,其他Fragment都继承它,BaseFragment可以做一些共有的操作。
出现的问题:
- 滑动时会默认加载左右两侧Fragment的数据,数据多时,滑动就会出现卡顿现象。
- 修改Fragment数据后,调用notifyDataSetChanged()方法失效。
问题分析:
- 我们知道ViewPager本身具有预加载的性质,所以它会默认加载左右两边的Fragment,视图和数据也就被初始化了。所以我们需要屏蔽掉ViewPager的预加载,或者让Fragment实现懒加载。
- notifyDataSetChanged()方法失效说明getItem方法没有重新调用,那就与我们继承的FragmentPagerAdapter有关系了。
三、FragmentPagerAdapter与FragmentStatePagerAdapter的区别
3.1 FragmentPagerAdapter
FragmentPagerAdapter类默认会对getItem()方法返回的Fragment做缓存处理,只有当第一次打开ViewPager的页面才会去创建Fragment的对象,后面再打开页面时就会直接从缓存中获取Fragment对象的引用,这样getItem方法就不会调用了。
因为FragmentPagerAdapter做了缓存处理,所有当创建很多的Fragment时内存就会吃不消,应用程序有可能会崩掉,所以呢,FragmentPagerAdapter不适合做大量数据的Fragment显示,比较适合数据不变的静态Fragment显示。
3.2 FragmentStatePagerAdapter
- FragmentStatePagerAdapter正好与之相反,每次进入页面时都会创建Fragment对象,每次滑出时都会销毁对应的Fragment对象,没有做一点的缓存,这样内存就完全的解放出来了。
FragmentStatePagerAdapter在销毁Fragment时会调用onSaveInstanceState方法保存一些数据信息,然后下一次创建Fragment时会将这些数据读取出来。
FragmentPagerAdapter与FragmentStatePagerAdapter具体区别还有很多,这里就不一一介绍了,有兴趣的朋友可以去百度搜一下。
四、ViewPager的预加载解决
ViewPager天生会加载左右两侧的页面,这是通过一个叫做DEFAULT_OFFSCREEN_PAGES的属性指定的,通过setOffscreenPageLimit(int)可以指定这个属性的值。
翻进setOffscreenPageLimit(int)的源码,发现要是给的值小于1,那还是默认为1,也就是说这个方法只能指定加载更多的页面。并不能解决问题。
既然ViewPager天生有这个属性,那我们就自己建一个天生也有这个属性的ViewPager,让其默认为0就好了。但是因为ViewPager源码已经改版了不知多少次,所以建议去GrepCode上找。
发现问题:
- 当我们把ViewPager改成自己的LazyViewPager之后,就不能与TabLayout绑定了,因为TabLayout只能与ViewPager对象绑定,这样就很尴尬了,能解决预加载问题,却不能解决绑定问题,说明这样也行不通了,那就只能把解决办法放到Fragment上了。
五、Fragment实现懒加载
- 既然前面ViewPager解决预加载发生冲突,那就只能自己解决加载数据的问题。
分析:Fragment的生命周期中,我们一般在onCreateView方法初始化视图,onActivityCreated方法初始化数据,正常创建Fragment对象后就会去加载视图和数据,需要我们这里需要控制加载数据的时机。
实现方式主要有两种,一是在页面选中后才去加载数据,二是当Fragment可见了才去加载数据。
第一种方式实现:
- BaseFragment中暴露一个加载数据的方法,监听ViewPager的滑动,当页面选中时再去加载数据。代码见Demo。
第二种方式实现:
通过setUserVisibleHint和getUserVisibleHint方法来设置和获取Fragment的显示状态,当显示了才去加载数据。因为每一个Fragment都是这样,所以在BaseFragment中完成操作。
@Override public void setUserVisibleHint(boolean isVisibleToUser) super.setUserVisibleHint(isVisibleToUser); if (getUserVisibleHint()) isVisible = true; lazyLoad(); else isVisible = false; onInvisible();
以上纯属于个人平时工作和学习的一些总结分享,如果有什么错误欢迎随时指出,大家可以讨论一起进步。如果你觉得对你有帮助,请到GitHub上star或者fork,谢谢。
以上是关于ViewPager详解填充Fragment和懒加载的主要内容,如果未能解决你的问题,请参考以下文章