ViewPager + Fragment 懒加载

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010289802/article/details/80701146

懒加载介绍

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

Fragment为我们提供了一个方法setUserVisibleHint(boolean isVisibleToUser),其中的参数isVisibleToUser就是表示该Fragment的UI对于用户是否可见。

setUserVisibleHint(boolean isVisibleToUser)方法会多次回调,而且可能会在onCreateView()方法执行完毕之前回调。如果isVisibleToUser==true,然后进行数据加载和控件数据填充,但是onCreateView()方法并未执行完毕,此时就会出现NullPointerException空指针异常。

基于以上原因,我们进行数据懒加载的时机需要满足两个条件:

  1. onCreateView()方法执行完毕
  2. setUserVisibleHint(boolean isVisibleToUser)方法返回true

完整代码

public class LazyFragment extends Fragment {

    private static final String TAG = "LazyFragment";
    private static final String NAME = "name";

    private String titlename ;
    //Fragment的View加载完毕的标记
    private boolean isViewCreated;
    //Fragment对用户可见的标记
    private boolean isUiVisible;

    private Unbinder unbinder;
    @BindView(R.id.swipe)
    SwipeRefreshLayout swipeRefreshLayout;
    @BindView(R.id.tv_title)
    TextView tvTitle;

    public static LazyFragment newInstance(String name) {
        LazyFragment fragment = new LazyFragment();
        Bundle bundle = new Bundle();
        bundle.putString(NAME, name);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        Log.i(TAG, "setUserVisibleHint -- " + isVisibleToUser);
        if (isVisibleToUser) {
            isUiVisible = true;
            lazyLoad();
        } else {
            isUiVisible = false;
        }
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            titlename = getArguments().getString(NAME);
        }
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View v = inflater.inflate(R.layout.fragment_lazy, container, false);
        unbinder = ButterKnife.bind(this, v);
        tvTitle.setText(titlename);
        return v;
    }

    //调用此方法代表 onCreateView() 方法执行完毕
    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Log.i(TAG, "onViewCreated");
        isViewCreated = true;
        lazyLoad();
    }

    private void lazyLoad() {
        //这里进行双重标记判断,是因为setUserVisibleHint会多次回调,并且会在onCreateView执行前回调,
        // 必须确保onCreateView加载完毕且页面可见,才加载数据
        if (isViewCreated && isUiVisible) {
            loadData();
            //数据加载完毕,恢复标记,防止重复加载
            isViewCreated = false;
            isUiVisible = false;
        }
    }

    private void loadData() {
        Log.i(TAG, "loadData");
        //模拟加载网络数据
        swipeRefreshLayout.setRefreshing(true);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                swipeRefreshLayout.setRefreshing(false);
            }
        }, 2000);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.i(TAG, "onDestroyView");
        unbinder.unbind();
        //页面销毁,恢复标记
        isViewCreated = false;
        isUiVisible = false;
    }
}

效果

猜你喜欢

转载自blog.csdn.net/u010289802/article/details/80701146