tablayout配合viewpager使用的时候,因为viewpager有预加载属性,我们看到一个界面,其实viewpager至少已经加载了两个界面,如果用户只是为了浏览一个界面,这个时候就会造成流量浪费了,那怎么实现只加载看得见的界面了。从viewpager的源码我们知道
setOffscreenPageLimit(int limit)的limit的值最小为1,即使我们给该方法传0也是没用的,源码会进行判断并保证预加载的值最小为1.所以我们可以考虑从fragment着手。当fragment被用户可见时,setUserVisibleHint()会调用且传入true值,当fragment不被用户可见时,setUserVisibleHint()则得到false值。而在传统的fragment生命周期里也看不到这个函数。我们可以通过setUserVisibleHint()方法来控制fragment加载。如果我们仅仅依靠setUserVisibleHint()方法来控制,当我们从第一个fragment直接点击到与它不相邻的fragment时,你会发现程序会报view控件空指针异常,原因是setUserVisibleHint()方法 执行在onAttach()方法之前,所以也就会执行在onCreatView之前,这个时候就造成了view都还没有初始化就开始使用view控件操作或者展示数据了。那么可以尝试在setUserVisibleHint()执行且返回true的时候,说明界面可见了,我们再判断控件是否完成初始化,两个条件同时满足了这个时候我们就可以去执行我们的加载数据操作了。具体实现方法如下:
public abstract class BaseLazyFragment extends Fragment { private static final String TAG="BaseFragment"; //Fragment的view加载完毕的标记; private boolean isViewCreat; //fragment对用户可见的标记; private boolean isUIVisible; @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); Log.v(TAG,"base------onViewCreated"); initView(view); isViewCreat=true; lazyLoad(); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); Log.v(TAG,"base------setUserVisibleHint"); //isVisibleToUser这个boolean值表示:该fragment的UI用户是否可见; if(isVisibleToUser){ isUIVisible=true; lazyLoad(); }else{ isUIVisible=false; } } protected abstract void initView(View view); public void lazyLoad(){ //这里进行双重标记判断,是因为setUserVisibleHint会多次回调,并且会在onCreateView执行前回调,必须确保onCreateView加载完毕且页面可见,才加载数据 if(isUIVisible&&isViewCreat){ Log.v(TAG,"base------lazyLoad"); loadData(); //数据加载完毕,恢复标记,防止重复加载 isUIVisible=false; isViewCreat=false; } } /** * 执行加载数据的地方 */ protected abstract void loadData(); }
我们就只要将viewpager中的fragment继承BaseLazyFragment方法就可以了然后在
loadData方法中执行加载数据等操作就完成了。以上是个人学习中整理的笔记,仅供参考,写的不对的地方欢迎指出。