Android-Fragment懒加载

2017/9/18 posted in  Android

生命周期

附上生命周期,帮助下面的学习。

20171031150938445629591.png
20171031150938445629591.png

何为懒加载

Fragment 的 UI 对用户可见时才加载数据

为什么需要

  • 需求要求,我们一般是等数据加载完毕之后才会初始化UI,但是可能需求会先让UI显示,再加载数据
  • 与ViewPager搭配使用的时候,ViewPager有缓存机制,比如三个页面,0,1,2,当我们处于1页面的时候0,2也都会加载好,如果数据量较大的话,体验会很差

实现原理

核心的点是判断UI的可见,Fragment提供了一个setUserVisibleHint(boolean isVisibleToUser)方法可以用来判断;

setUserVisibleHint方法

  • 单个 Fragment,setUserVisibleHint 是不会被调用的,只有该 Fragment 在 ViewPager 里才会被调用
  • 执行顺序:setUserVisibleHint 方法在Fragment的生命周期函数之前执行一次,此时isVisibleToUser是false,后续还会执行一次,此时isVisibleToUser是true,但是这次的时间是不确定的 。参考官方note说明

20171031150938453113981.png
20171031150938453113981.png

实现代码

public class FriendFragment extends Fragment {

    private boolean isVisible;
    // 标志位,标志已经初始化完成,防止空指针的异常
    private boolean isViewCreated;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        super.onCreateView(inflater, container, savedInstanceState);
        isViewCreated = true;
        View chatView = inflater.inflate(R.layout.activity_tab_friend, container,false);
        return chatView;
    }


    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
              Log.e("hhp", "setUserVisibleHint: isVisibleToUser--"+isVisibleToUser+"---isViewCreated---"+isViewCreated );
        if (isVisibleToUser && isViewCreated) {
            isVisible = true;
            lazyLoad();
        }else {
            isVisible = false;
        }
    }

    private void lazyLoad() {
        if (!isVisible || !isViewCreated) {
            return;
        }
        getData();
    }

    private void getData() {
        //加载数据
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (getUserVisibleHint()) {
            getData();
        }
    }
}

几点说明

分析两种情况:

1.进来就加载的这个Fragment,此时isVisibleToUser 和isViewCreated 两个标志位的值如下

20171031150938465135328.png
20171031150938465135328.png

,无法加载数据 ,所以需要在onActivityCreated方法中调用加载数据

2.进来加载的不是这个Fragment,当该Fragment被缓存的时候,调用onActivityCreated方法getUserVisibleHint()值是false,不调用getData()方法;同理,isVisibleToUser和isViewCreated也是false,也不会调用getData()方法;滑动到该Fragment的时候,onActivityCreated方法不会再次执行,isVisibleToUser和isViewCreated都变为true,调用getData()方法加载数据。