一、引言
LazyLoad,见文知意,就是懒惰地加载。理念和单例模式中的懒汉模式有异曲同工之处。
在做一个APP的时候,一个ViewPager包含多个Fragment,如果在打开APP的时候每个fragment自动加载,不管是从本地还是网络,都会占用一定的资源。
那我们可以不可以让这个fragment在需要被显示的时候才去加载、初始化呢?
在Fragment中有一个方法——setUserVisibleHint就能实现这个设想。
二、setUserVisibleHint的使用
setUserVisibleHint方法用于告诉系统,这个Fragment的界面对用户当前是否是可见的。所以我们只需要继承Fragment并重写该方法,即可实现在fragment可见时才进行数据加载操作,即Fragment的懒加载。
代码解释:
1.代码开始先设定标志变量isInit代表视图是否已经初初始化,在视图初始化的时候设置为true
标志变量isLoad代表视图是否对用户可见,在视图可见时设为true
2.定义了一个判断是否可以加载数据的方法isCanLoadData() ,*可以加载数据的条件:
* 1.视图已经初始化,isInit==true
* 2.视图对用户可见,getUserVisibleHint()返回true
3.定义了一个lazyLoad的抽象方法,该方法在isCanLoadData()里面调用。起到当视图初始化并且对用户可见的时候去真正的加载数据的作用。
4.定义了一个stopLoad方法,用于在切换到其他页面时停止加载数据。
5.定义方法onDestroyView,视图销毁的时候将Fragment的状态是否初始化变为false。
isInit = false;
isLoad = false;
6.视图是否已经对用户可见,系统的方法setUserVisibleHint(),在其中调用 isCanLoadData方法,实现Fragment数据的缓加载.
代码:
public abstract class LazyLoadFragment extends Fragment {
/**
* 视图是否已经初初始化
*/
protected boolean isInit = false;
protected boolean isLoad = false;
protected final String TAG = "LazyLoadFragment";
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(setContentView(), container, false);
isInit = true;
/**初始化的时候去加载数据**/
isCanLoadData();
return view;
}
/**
* 视图是否已经对用户可见,系统的方法
*/
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
isCanLoadData();
}
/**
* 是否可以加载数据
* 可以加载数据的条件:
* 1.视图已经初始化
* 2.视图对用户可见
*/
private void isCanLoadData() {
if (!isInit) {
return;
}
if (getUserVisibleHint()) {
lazyLoad();
isLoad = true;
} else {
if (isLoad) {
stopLoad();
}
}
}
/**
* 视图销毁的时候讲Fragment是否初始化的状态变为false
*/
@Override
public void onDestroyView() {
super.onDestroyView();
isInit = false;
isLoad = false;
}
protected void showToast(String message) {
if (!TextUtils.isEmpty(message)) {
Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show();
}
}
/**
* 设置Fragment要显示的布局
*
* @return 布局的layoutId
*/
protected abstract int setContentView();
/**
* 获取设置的布局
*
* @return
*/
protected View getContentView() {
return view;
}
/**
* 找出对应的控件
*
* @param id
* @param <T>
* @return
*/
protected <T extends View> T findViewById(int id) {
return (T) getContentView().findViewById(id);
}
/**
* 当视图初始化并且对用户可见的时候去真正的加载数据
*/
protected abstract void lazyLoad();
/**
* 当视图已经对用户不可见并且加载过数据,如果需要在切换到其他页面时停止加载数据,可以覆写此方法
*/
protected void stopLoad() {
}
}
三、注意
isCanLoadData方法也在onCreateView中进行了调用,是因为要进行初始化的工作,毕竟ViewPager是会默认显示第一页的。setUserVisibleHint 的执行顺序又是在 onCreatView 之前,同时 onCreatView 需要初始化界面和修改 isInit 的值。
setUserVisibleHint 的执行顺序是
setUserVisibleHint(false) -> onAttach -> onCreate -> setUserVisibleHint(true) -> onCreateView -> onActivityCreated ->…. -> onDetach参考ITluochen同学的blog