ViewPager+Fragment+TabLayout —— 实时加载数据

引言

ViewPager + Fragment + TabLayout的模式已经很常见了,例如今日头条等等,如果今日头条是ViewPager + Fragment + TabLayout的实现方式,那表现形式上就是一个ViewPager管理多个Fragment,左右滑动来回切换。而ViewPager有一特性(预加载),比如打开应用,先看到的是Tab1(推荐),但这时候Tab2(热点)已经加载好了。当切换到Tab2(热点),Tab3(所在的城市)已经加载好了(前提是没有自己处理)。

但是上面所说ViewPager + Fragment + TabLayout的这种组合并不是通用的,因为有时候用户希望选择了哪个Tab再去加载哪个Tab的数据,而不是预加载,如果当前页面和预加载页面都有大量的网络请求,可能就会比较慢。(但是如果数据量较少的话切换能更顺畅,根据自己的需求去选择吧)关于这个问题,众说纷纭,比如弃用ViewPager,或者直接禁掉ViewPager预加载。

其实那些说通过调用ViewPager的setOffscreenPageLimit(int limit),来设置ViewPager预加载的数量,来达到禁止预加载。这是不行的,因为ViewPager中的这个默认值为1,具体源码如下:

private static final int DEFAULT_OFFSCREEN_PAGES = 1;

...此处省略

public void setOffscreenPageLimit(int limit) {
        if (limit < DEFAULT_OFFSCREEN_PAGES) {
            Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
                    + DEFAULT_OFFSCREEN_PAGES);
            limit = DEFAULT_OFFSCREEN_PAGES;
        }
        if (limit != mOffscreenPageLimit) {
            mOffscreenPageLimit = limit;
            populate();
        }
    }

根据查看源码,ViewPager中DEFAULT_OFFSCREEN_PAGES 默认值为1,即默认会预加载当前页面左右各一个页面,如果你设置的值小于默认值,它依然设置的是1。

看到这里你是不是想说:“既然它的默认值1,那是不是可以自己写一个ViewPager,代码一样,只是把默认值修改为0?”其实理论上是可以的,但是…目前Android的API已经更新到27了,而且每个版本v4包是有差异的。所以如果要实现选择了哪个Tab再去加载哪个Tab的数据,可以使用下文方案。

加载方案

依靠Fragment的setUserVisibleHint(boolean isVisibleToUser)的方法,我们可以在这个方法里做判断,当其true时(当前fragment视图用户可见)时再去加载数据。

setUserVisibleHint(boolean isVisibleToUser)方法会在界面可见和不可见都会调用,而且fragment首次加载时此方法会在onCreateView之前调用,所以直接在此方法中去加载数据,可能会导致空指针异常,所以得确保视图初始化以后(isInit = true),再去加载数据。如下:

@Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_all_order, container, false);
        init(view);
        return view;
    }

    private void init(View view) {
        isInit = true;
        presenter = new PayOrderPresenter();
        presenter.setView(this);

        emptyView = view.findViewById(R.id.empty_layout);
        recyclerView = (PtrDefRecyclerView) view.findViewById(R.id.recycler_view);
        LinearLayoutManager manager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(manager);

        recyclerView.setOnLoadListener(this);
        recyclerView.setOnRefreshListener(this);

        mAdapter = new AllOrderAdapter();
        recyclerView.setAdapter(mAdapter);
    }

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

        if (isVisibleToUser) {
            if (isInit) {
                //加载数据
                loadData();
            }
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        isInit = false;
    }

这样就能够保证加载数据的时候不会出现空指针异常,而且每次切换到当前fragment的时候都会去加载数据,也达到了利用ViewPager的预加载来初始化视图。

PS:以上仅仅是自己在开发中实现的方案,如果各位大佬有更好或者更简单的方案,欢迎分享学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值