在开发的时候经常使用ViewPager + Fragment ,但是你真的了解他是怎么执行的吗,是时候进行一下总结了。
1,ViewPager的适配器
FragementPagerAdapter和FragmentStatePagerAdapter
FragmentPagerAdapter中,即使fragment不可见了,他的事他实例还是存在于内存中,当 fragment比较多的时候,会占用较大的内存.
FragmentStatePagerAdapter,当fragment不可见时,可能会将fragment的实例会销毁,所以内存占会小一些
2,ViewPager 的缓存机制
ViwePager 的缓存机制会默认缓存旁边的页面,是为了让页面更加流畅.在缓存旁边页面的时候会执行到onCreateView方法,如果你两个碎片的onCreateView 中都有执行请求数据的时候,旁边的页面也会发送请求,这样就会造成网络请求的一些问题。
使用setOffscreenPagerLimit方法可以设置缓存页面的个数,默认为1,就算你传入负数他还是默认缓存旁边页面,也就是1
由于ViewPager的默认缓存是1,所以ViewPager中至少会预加载一个页面的数据。如果页面有请求数据或者下载数据的时候,这就会影响当前显示的页面。
我们知道在碎片中 只有在onCreateView方法中才可以拿到View 然后加载控件进行一些数据的设置.但是当碎片在ViewPager中的时候,缓存机制会导致旁边的页面中的onCreateView方法执行,这就是我们不想看到的结果。
Fragment里面有一个方法 setUserVisibleHint(boolean isVisibleToUser)方法,这个方法可以判断当前页面是否对用户可见。
还有一点,当ViewPager缓存了旁边的那个碎片之后,那个碎片执行onCreateView之后,他碎片的生命周期会失效。当他被缓存抛弃的时候这个碎片就会被销毁。直到他又一次被缓存或者当他可见的时候才会执行onCreateView方法。
3,懒加载实现
定义所有碎片的基类,也就是让所有碎片继承这个类,他是一个抽象类
public abstract class FragmentFactory extends Fragment {
private boolean isViewInitFinished;
//当Fragment所在的Activity被启动完成后回调该方法
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
isViewInitFinished = true;
// 当前页面是否可见
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser && isViewInitFinished){
getData();
public abstract void getData();
}
让ViewPager里面要显示的碎片继承这个类并实现他的方法,在这个方法里面就可以去执行你的逻辑了。记住当实现懒加载的时候就不要在onCreateView方法执行逻辑了。当碎片加载的时候会调用父类的setUserVisibleHint方法。后判断是否是当前页面,如果是就可以在重新父类的方法中进行操作了。
SetUserVisibleHint方法是执行在最前面的,他会在ViewPager里面Fragment生命周期还没执行的时候调用.
请注意SetUserVisibleHint方法调用的次数,在刚开始的时候会根据你设置的ViewPager的缓存个数去调用SetUserVisibleHint方法,然后Fragment显示后会在调用一次SetUserVisibleHint方法。也就是说在Fragment生命周期之前ViewPager会根据缓存个数去调用SetUserVisibleHint方法。当调用完成后,Fragment的生命周期会开始,这个时候Viewpager就会再次调用SetUserVisibleHint方法判断当前的fragment是否被显示。所以在SetUserVisibleHint中判断是否是当前页面的时候 都要判断一下 在onActivityCreated中的布尔变量是否为真,必须在这个布尔为真的时候才可以去判断当前Fragment有没有显示。
这种懒加载在官方文档中给出了明确的说明
/**
* Created by hjm on 2017/4/13 15:40.
public abstract class BaseFragment extends Fragment {
private boolean isViewInitFinished;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
isViewInitFinished = true;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
requestData(isVisibleToUser);
public void requestData(boolean isVisibleToUser){
if(isViewInitFinished && isVisibleToUser){
getData();
* this moment the fragment is visiable to user, so request data
##### #### #### #### #### ** */**
public abstract void getData();
}
本人也是新手,如有错误请指出,谢谢!
本节带来的是Android 3.0后引入的一个UI控件——ViewPager(视图滑动切换工具),实在想不到如何来称呼这个控件,他的大概功能:通过手势滑动可以完成View的切换,一般是用来做APP的引导页或者实现图片轮播,因为是3.0后引入的,如果想在低版本下使用,就需要引入v4兼容包,我们也可以看到,ViewPager在:android.support.v4.view.ViewPager目录下。下面我们就来学习一下这个控件的基本用法。
严格来说来说不是类的懒加载,而是针对业务中的特殊需求实现的,让fragment在可见的时候再进行网络请求。
在viewpager+PagerFragentAdapter里面的Fragment里面,初次加载时,offset范围内的所有fragment的oncreateView方法都会执行,默认情况下,fragment原有的逻辑中,页面的初始化和网络请求都会触发,这就会导致初次进入时,即使在用户面前只展示了一个tab和fragment,但是却所有tab下页面的数据都请求了,会浪费用户流量。正确的做法是在用户打开fragment之后才请求数据。
我的简书同步发布:ViewPager源码分析(2):滑动及冲突处理
转载请注明出处:【huachao1001的专栏:http://blog.csdn.net/huachao1001】
上一篇介绍了ViewPager的onMeasure和onLayout两个方法,这是自定义View最基本的两个函数。但是我们的ViewPager有个需求就是滑动,接下来我们一起去学习ViewPager在滑动方面做了哪些工作,以及ViewPager如何处理与子View之间的滑动冲突。由于ViewPager的子View有Decor View还有普通的子View,而本篇文章讲的主要是普通子View,因此,不再去刻意区
在使用 ViewPager 时 , 如果我们的适配器使用的是 FragmentStatePagerAdapter ,那么当我们重新滑到之前已销毁的页面时,一般情况下页面的状态依然将保持不变(比如 RecyclerView 的 滚动位置等,EditText 的 输入内容 等), 或者说 View 历史状态被还原了。
本文的主旨就是解释其 保存与还原内部的原理以及过程。
ViewPager刷新问题原理分析及解决方案(FragmentPagerAdapter+FragementStatePagerAdapter)
ViewPager刷新问题原理分析及解决方案(FragmentPagerAdapter+FragementStatePagerAdapter)
一道面试题:ViewPager中的Framgent如何实现懒加载?
setUserVisiblity已被废弃,推荐使用 setMaxLifecycle 处理 Fragment 在 ViewPager 中的懒加载