ViewPager+Fragment的懒加载模式

本文介绍了一种优化ViewPager+Fragment组合的方式,通过禁止预加载并仅在Tab被选中时加载数据,有效减少不必要的网络请求,提高用户体验。

ViewPager+Fragment的模式再常见不过了,以国民应用微信为例,假设微信也是ViewPager+Fragment的实现方式,那表现形式上就是一个ViewPager管理了四个Fragment,左右滑动来回切换。但是ViewPager有一个奇葩的特性叫:预加载,比如打开微信,首先看到的是第一个Tab(微信),但事实上第二个Tab(通讯录)已经加载好了。当选择第二个Tab(通讯录),第三个Tab(发现)已经加载好了,以此类推。


但上述ViewPager+Fragment的这种组合并不完美,因为我希望用户选择了哪个Tab再去加载哪个Tab的数据,而不要去做预加载,假如当前页面和预加载页面都有大量的网络请求,可能就会比较慢,有很多请求在排队。关于这个问题,也有很偏激的做法,比如弃用ViewPager,自己手动管理Fragment,或者直接禁掉ViewPager预加载。有一种比较合适的方案是保持ViewPager预加载的特性,但是只初始化View,选择当前Tab的时候再进行网络请求。关于这一方案的实现,也是众说纷纭,千奇百怪。最后,还是选择男神Stay的方案。


直接上代码。


public abstract class BasePageFragment extends Fragment {

 

    protected boolean isViewInitiated;

    protected boolean isVisibleToUser;

    protected boolean isDataInitiated;

 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

    }

 

    @Override

    public void onActivityCreated(Bundle savedInstanceState) {

        super.onActivityCreated(savedInstanceState);

        isViewInitiated = true;

        prepareFetchData();

    }

 

    @Override

    public void setUserVisibleHint(boolean isVisibleToUser) {

        super.setUserVisibleHint(isVisibleToUser);

        this.isVisibleToUser = isVisibleToUser;

        prepareFetchData();

    }

 

    public abstract void fetchData();

 

    public boolean prepareFetchData() {

        return prepareFetchData(false);

    }

 

    public boolean prepareFetchData(boolean forceUpdate) {

        if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {

            fetchData();

            isDataInitiated = true;

            return true;

        }

        return false;

    }

 

}


这是一个父类,看代码这里只有一个setUserVisibleHint需要说下,这是一个相当生僻的方法,我们可以用这个方法来判断当前UI是否可见,所以在prepareFetchData方法里我们做如下判断:就是当前UI可见,并且fragment已经初始化完毕,如果网络数据未加载,那么请求数据,或者需要强制刷新页面,那么也去请求数据,So easy。子Fragment只需要继承父类,实现抽象方法,在fetchData()里做网络请求或者其他耗时操作即可。再在写个子类吧。


public class PageFragment extends BasePageFragment {

 

    public static PageFragment newInstance(String title){

        PageFragment fragment = new PageFragment();

        Bundle args = new Bundle();

        args.putString("key_fragment_title", title);

        fragment.setArguments(args);

        return fragment;

    }

 

    private String title;

    private TextView tv;

 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        title = getArguments().getString("key_fragment_title");

        Trace.d(title + ":onCreate");

    }

 

    @Override

    public void onResume() {

        super.onResume();

        Trace.d(title + ":onResume");

    }

 

 

    @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        Trace.d(title + ":onCreateView");

        tv = new TextView(getActivity());

        return tv;

    }

 

    @Override

    public void fetchData() {

        tv.setText(title);

        /** * 在这里请求网络。 */

    }

 

}


如果你也有这样的需求或者烦恼,保证药到病除。


有同学说实践过程中遇到了些问题,比如Fragment只刷新一次,这个问题只要手动调用prepareFetchData(),传true即可强制刷新了。还有同学质疑setUserVisibleHint()和onActivityCreated()的执行先后的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值