Fragment 懒加载

为何懒加载

在很多 App 都会有 ViewPage + Fragment 的基本组合,但是众所周知 viewPager 的 预加载机制,即使设置函数 setOffscreenPageLimit(0)也不能改变默认值为 1 的事实,这样最少也会加载 3 个fragment,无疑对 app 的性能有所影响。

何谓懒加载

所谓的懒加载,其实也就是延迟加载,就是等到该页面的UI展示给用户时,再加载该页面的数据(从网络、数据库等),而不是依靠ViewPager预加载机制提前加载两三个,甚至更多页面的数据.这样可以提高所属Activity的初始化速度,也可以为用户节省流量.而这种懒加载的方式也已经/正在被诸多APP所采用.

怎样懒加载

核心函数 : Fragment$setUserVisibleHint(boolean isVisibleToUser)Fragment$getUserVisibleHint()

实现的功能

  • 在 Fragment 不显示时,不进行页面加载。 此时则需要setUserVisibleHint(boolean isVisibleToUser)来进行获取是否可见标志。
  • 在 Fragment 没有创建完成时,不进行页面加载。此时需要 boolean hasCreate来标记 当前 Fragment 是否完成初始化,完成初始化则 hasCreatetrue
  • 根据当前 Fragment 是否需要初始化,添加标志位 boolean needInit,在当页面对用户可见并且当前页面还没有加载时,该标志位 needInit置位为 true, 当前页面在加载结束后标志位needInit 置位为 false

具体代码 基类 LazyFragment


    public boolean hasLoaded = false;  //标识是否已经加载过
    private boolean hasCreated = false; //标识onCreateView是否已调用
    private boolean needInit = false;   //标识是否需要在onCreateView中```

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.i("lazy_load", "LazyFragment onCreateView. ");

        View rootView = inflater.inflate(R.layout.fragment_lazy, container, false);
        progressBar = $(rootView, R.id.fragment_lazy_progress_bar);
        content = $(rootView, R.id.fragment_lazy_content_wrapper);

        if (needInit) {
            initWrapper();
            needInit = false;
        }
        hasCreated = true;

        return rootView;
    }

    //首先执行,比onCreateView 早
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        Log.i("lazy_load", "LazyFragment setUserVisibleHint " + isVisibleToUser);
        Log.i("lazy_load", "LazyFragment setUserVisibleHint---- " + hasLoaded);

        if (isVisibleToUser && !hasLoaded) {    //如果当前Fragment向用户展示且没有加载过,进行下一步判断
            if (hasCreated) {   //如果onCreateView已经被创建,此时进行加载
                initWrapper();
            } else {        //如果Fragment没有创建,那么设置标记,在onCreateView中加载
                needInit = true;
            }
        }
    }

    /**
     * 此函数开始数据加载的操作,且仅调用一次
     */
    private void initWrapper() {

        LayoutInflater.from(getContext()).inflate(setContentView(), content);
        initialize();
        fadeOutView(progressBar, mShortAnimationDuration);
        fadeInView(content, mShortAnimationDuration);
        hasLoaded = true;
        Log.i("lazy_load", "LazyFragment initWrapper " + hasLoaded);
    }

    /**
     * 供子类使用,子类fragment初始化操作,此函数内部真正开始进行页面的一些列操作
     */
    abstract void initialize();

    /**
     * 子类fragment设置布局,返回fragment要设定的布局
     *
     * @return 子类fragment要显示的布局
     */
    @LayoutRes
    abstract int setContentView();

参考博客:

吴小龙同學 - Android ViewPager + Fragment 懒加载实现
ViewPager+Fragment组合的预加载和懒加载

其实该问题还涉及的有:

如何更新及替换ViewPager中的Fragment – 细节
Android Fragment的生命周期和返回栈

猜你喜欢

转载自blog.csdn.net/strange_monkey/article/details/80529150
今日推荐