Fragment懒加载
在App中使用ViewPager+Fragment的结构是很常见的,由于ViewPager的机制是预加载的,所以当我们滑动当前页的时候会预先加载其他的Fragment,这就导致了当我们对某些页面不感兴趣时,其实已经访问完网络了,如何去解决这个问题可以使用懒加载的思想。
在这里主要利用setUserVisibleHint(boolean isVisibleToUser)函数回调,此函数在Fragment可见或者不可见时都会调用。但是光靠这个方法是不够的我们还要通过一个标记位来判断是否已经加载过了。
这里我们写一个BaseFragment类来进行管理
BaseFragment:
public abstract class BaseFragment extends Fragment {
//根布局
protected View rootView;
//当前Fragment是否显示
protected boolean isVisible;
//是否加载过了
protected boolean isReady;
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
isReady = true;
onLazyLoad();
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getUserVisibleHint()) {
isVisible = true;
onVisible();
} else {
isVisible = false;
onInvisible();
}
}
protected void onVisible() {
onLazyLoad();
}
private void onLazyLoad() {
if (isVisible && isReady) {
System.out.println("BaseFragment.onLazyLoad");
//这地方一定要注意,一定要将isReady改成false,否则懒加载无效
isReady = false;
initData();
}
}
//可以访问网络请求数据
protected abstract void initData();
//可以对一些控件进行隐藏,或者终止动画
protected abstract void onInvisible();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (rootView == null) {
rootView = inflater.inflate(provideContentViewId(), container, false);
initView(rootView);
}
return rootView;
}
protected abstract void initView(View rootView);
abstract int provideContentViewId();
}
为了不让onViewCreated再有机会运行(因为这个方法在运行还会调用isReady=true,就没法实现懒加载),我们应该使用setOffscreenPageLimit这个方法进行预加载(这样就会保证划出去的Fragment不会调用onDestroyView,下次滑进来不会再回调onViewCreated)
如果我们想对懒加载的页面进行刷新,可以增加一个下拉刷新的控件等等。
我们还需要在初始化PagerAdapter的时候加上这句话:
viewPager.setOffscreenPageLimit(2);
分析:
我有三个Fragment在ViewPager里面,此方法是预加载两页,默认是一页。例如当我们在第n页就会加载n-2,n-1,n,n+1,n+2。
因为我们在onViewCreated中设置了isReady=true,如果我们设置setOffscreenPageLimit为1时,当我们切换到第三个Fragment时(此时第一个Fragment会调onDestroyView),当我们从第三个Fragment切换到第二个Fragment时,又会调用第一个Fragment的onViewCreated方法,这样isReady=true又会执行一遍,所以又会调用onLazyLoad(),所以这是我们不想看到的。
当程序第一次进入时就会懒加载FragmentOne,反复切换,保障每个Fragment只运行了一个onLazyLoad方法。
结果:
群号:365473065
微信公众号: