ViewPager + Fragment中对Fragment数据懒加载的实现

背景

  • 项目中不可避免会用到,这里记录一下,方便自己和同学们,好记性不如烂笔头。

  • 理解后就不用专门记了,因为也确实没有太多复杂的东西。

  • 因为 viewPager 的预加载机制,所以我们为了让 fragment 使用起来更加流畅,提升性能,所以需要对 fragment 做一个懒加载的操作,当 fragment 对用户不可见时不加载数据。


分析实现

  • 最开始的 fragment 代码如下:
package com.example.myapplication.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.myapplication.R;

/**
 * 懒加载写法
 */
public class MyFragment extends Fragment {


    public MyFragment() {
        // Required empty public constructor
    }

    private View view;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        if (view == null && savedInstanceState == null){
            view = inflater.inflate(R.layout.fragment_my, container, false);
        }

        return view;
    }
}

这个没有疑问。


  • 只有当 fragment 对用户可见fragment 的视图已经加载完成以后,我们才可以做对应的数据加载操作,所以这里引入两个布尔变量分别标识,如下图示:
    在这里插入图片描述

初始化均赋值为 false。


  • 因为是跟 viewPager 相结合,所以在 fragment 中判断对用户是否可见我们重写setUserVisibleHint生命周期方法进行判断,如下图示:
    在这里插入图片描述

  • 在 onCreateView 方法中对view已经加载完成标识置为 true,如下图示:
    在这里插入图片描述

  • 所以此时当对用户可见且 view 已经加载完成后,我们在 onResume 方法中做懒加载操作,如下图示:
    在这里插入图片描述

  • 此时做完懒加载操作后,记得恢复先前的标识,防止数据重复加载。如下图示:
    在这里插入图片描述

  • 因为预加载机制,有的 fragment 已经初始化完成了,也执行到了 onResume 生命周期方法,但是这时候对用户不可见,所以在 onResume 方法里的 lazyLoad 方法并不会执行,那么这种情况下也就不会执行懒加载操作。

  • 不过这个时候,当滑动fragment 对用户可见时,会回调 setUserVisibleHint 生命周期方法,所以我们可以在这里面进行懒加载操作,也就解决了上面说的情况。如下图示:
    在这里插入图片描述


  • 最后,可能有的同学会说,你第一次创建fragment的时候,在 setUserVisibleHint 中调用了 lazyLoad 方法,也在 onResume 中调用了 LazyLoad 方法,你这不是就重复加载数据了吗?

  • 说明如下:因为 setUserVisibleHint 方法会优先于 onCreateView 方法执行(如下图示),所以此时 view 还未加载完,那么上面所说的 isViewCreated 标识值为 false ,所以此时 lazyLoad 方法其实并不会执行。因为只有同时满足对用户可见且 view 已经加载完成才去加载数据。
    在这里插入图片描述
    所以问题得以解决。


完整代码

package com.example.myapplication.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.myapplication.R;

/**
 * 懒加载写法
 */
public class MyFragment extends Fragment {

    private boolean isVisible = false;// 对用户是否可见标识
    private boolean isViewCreated = false;// view是否已经加载完成标识

    public MyFragment() {
        // Required empty public constructor
    }

    private View view;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        if (view == null && savedInstanceState == null){
            view = inflater.inflate(R.layout.fragment_my, container, false);
        }

        isViewCreated = true;// view 已经加载
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        lazyLoad();
    }

    /**
     * 延迟加载 - 对用户可见且view已经加载完成
     */
    private void lazyLoad() {
        if(isVisible && isViewCreated){
            loadData();
            reset();// 恢复标识,防止重复加载
        }
    }

    /**
     * 恢复标记 防止重复加载
     */
    private void reset(){
        isViewCreated = false;
        isVisible = false;
    }

    /**
     * 加载数据操作
     */
    private void loadData() {

    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser){

            isVisible = true;// 对用户可见
            lazyLoad();

        }else {
            isVisible = false;// 对用户不可见
        }
    }
}

上面就是完整的一个懒加载实现的代码,希望对同学们加深理解有帮助。


技术永不眠,我们下期见!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章