关于 对lazyload的原理进行的学习

一、引言

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 
     * @return
     */
    protected  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

你可能感兴趣的:(Android)