viewpager嵌套fragment,数据预加载的问题

本文深入探讨了在使用ViewPager嵌套Fragment时遇到的预加载问题,通过分析源码揭示了问题根源,并提供了一种有效解决方案。
前几天做项目的时候用到了viewpager嵌套fragment,以前都是用的第三方的,没有出现过问题,前几天做的时候发现,在fragmentA加载数据的时候,加载框一直转,等到fragmentA加载数据完成,还在转,一直不明白为什么,原以为是封装的加载框出问题了,偶然间发现是因为后边两个fragmentB和fragmentC没有加载完数据,所以加载框一直旋转个不停,没办法,先去掉加载框,就那么运行了。

今天正好有时间,研究下哪里出的问题,发现原来是viewpager的问题,viewpager有预加载的功能,如果不明白的可以看我之前发过的一篇博文,

连接http://blog.youkuaiyun.com/sinat_29874521/article/details/52869253

好了,言归正传,感谢http://www.cnblogs.com/wangfeng520/p/5807465.html提供的帮助,里边说的很详细,用的方法也很好

源码

   /**
     * Set a hint to the system about whether this fragment's UI is currently visible
     * to the user. This hint defaults to true and is persistent across fragment instance
     * state save and restore.
     *
     * <p>An app may set this to false to indicate that the fragment's UI is
     * scrolled out of visibility or is otherwise not directly visible to the user.
     * This may be used by the system to prioritize operations such as fragment lifecycle updates
     * or loader ordering behavior.</p>
     *
     * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default),
     *                        false if it is not.
     */
    public void setUserVisibleHint(boolean isVisibleToUser) {
        if (!mUserVisibleHint && isVisibleToUser && mState < STARTED) {
            mFragmentManager.performPendingDeferredStart(this);
        }
        mUserVisibleHint = isVisibleToUser;
        mDeferStart = !isVisibleToUser;
    }
需要注意的是这个方法会在Fragment的onCreate()方法调用之前就调用
    /**
     * @return The current value of the user-visible hint on this fragment.
     * @see #setUserVisibleHint(boolean)
     */
    public boolean getUserVisibleHint() {
        return mUserVisibleHint;
    }

原谅我英语不好,我就不翻译了,说白了就是一句话

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

    }
这里isVisibleToUser,就是判断该fragment是否是用户可见的视图,如果是则为true,不是则是false。而getUserVisibieHint()则是用来获取状态信息的,可见是true,不可见是false

用法当然更简单了

当然,还需要看一个方法的源码

    /**
     * Return true if the fragment is currently visible to the user.  This means
     * it: (1) has been added, (2) has its view attached to the window, and 
     * (3) is not hidden.
     */
    final public boolean isVisible() {
        return isAdded() && !isHidden() && mView != null
                && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE;
    }
用来做判断的,很容易理解,isVisible()方法可以判断Fragment的视图是否创建好,对于第一个显示的Fragment,因为isVisibleToUSer是true,但是isVisible()是false,那么在显示第一个Fragment的时候是空白的。但是对于其它的Fragment,因为存在ViewPager的预加载,当显示到Fragment的时候,isVisible()是true,而不是false。所以会在这个方法里面进行加载数据的操作

好了说下用法

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(isVisibleToUser && isVisible()){
            setDatas();//获取数据
        }
    }
双重判断,省的做其他逻辑处理
    @Override
    public void onResume() {
        super.onResume();
        if(getUserVisibleHint()){
            isFresh = true;
            setDatas();
        }
    }
因为我的获取数据的方法是刷新和加载全部卸载一起了所以isFresh = true可以忽略,之所以我这么写,不会重复加载数据,是因为我在获取初始化数据的时候,清空了数据集合,当然,这么做处于用户考虑,肯定不合理,毕竟费流量啊,不过其他的不考虑了,后续修改

PS:为何setUserVisibleHint()明明在onCreate()之前执行,但是还可以在里边写获取加载数据的方法呢?原因很简单,就是因为viewpager有预加载的功能,所以在进入这个fragment之前,viewpager就把这个fragment的控件加载完成了,而因为这个fragment是不可见的,所以isVisible()方法就是false,而不会运行加载数据的方法,但是说明一下,setUserVisibleHint()不是随着fragment的生命周期运行的,而是需要手动调用的,自己运行一下debug就明白了,回归正题,因为viewpager已经加载完成了所有控件,所以在运行到该fragment,该fragment可见,那么运行setUserVisibleHint(),而此时控件已经被viewpager预加载完成,isVisible()则是true,所以就可以吧加载数据的方法下载里边了。

反正我是这么理解的,如果有不对的地方请指出来,谢谢!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值