美文网首页AndroidAndroid面试Android转载
Android之Fragment懒加载分析

Android之Fragment懒加载分析

作者: 于阗 | 来源:发表于2016-07-06 17:24 被阅读9982次

    Android应用开发时,我们经常会碰到一个Activity内使用ViewPager包含多个Fragment的情况。由于ViewPager的预加载功能,通过setOffscreenPageLimit(int number) 来设置预加载,默认的预加载是1,但是即使你设置为0,也是不起作用的,设置的只能是大于1才会有效果。这无疑会为性能上带来很大影响。解决这个问题有两种方式,一种是禁止ViewPager的预加载,重写ViewPager,但是该方法会出现左右滑动时会出现卡顿现象,带来不好的用户体验。而另外一种就是我们接下来要讲的通过Fragment的懒加载来实现。当用户切换到某个fragment时再加载。

    通过查看Fragment的源码可以发现它有setUserVisibleHint()这个方法,源码如下:

    /** * 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 < STARED){
              mFragmentManager.performPendingDeferredStart(this);
      }
      mUserVisibleHint = isVisibleToUser;
      mDeferStart = !isVisibleToUser;
    }
    

    该方法用于告诉系统,这个Fragment的UI是否是可见的。所以我们只需要继承Fragment并重写该方法,即可实现在fragment可见时才进行数据加载操作,即Fragment的懒加载。

    使用时,写一个基类BaseFragment,继承它即可,代码如下:

    /**
     * User: Hlh(tatian91@163.com)
     * Date: 2016-07-04
     * Time: 09:37
     */
    public abstract class BaseFragment extends Fragment {
        //是否可见
        protected boolean isVisble;
        // 标志位,标志Fragment已经初始化完成。
        public boolean isPrepared = false;
      
        /**
         * 实现Fragment数据的缓加载  
         * @param isVisibleToUser
         */
        @Override
        public void setUserVisibleHint(boolean isVisibleToUser) {
            super.setUserVisibleHint(isVisibleToUser); 
           if (getUserVisibleHint()) {
                isVisable = true; 
               onVisible();
            } else {
                isVisable = false;
                onInVisible();
            } 
       }
        protected void onInVisible() {
        }
        protected void onVisible() {
            //加载数据
            loadData();
        } 
       protected abstract void loadData();
    }
    

    在BaseFragment中增加了三个方法,一个是onVisible ,当fragment可见时调用。一个是onInvisible,当fragment不可见时调用。另外一个是loadData。

    public class TabFragment extends BaseFragment{  
     
        @Override  
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
            Log.d(LOG_TAG, "onCreateView");  
            View view = inflater.inflate(R.layout.fragment_tab, container, false);  
            //初始化view的各控件  
            isPrepared = true;  
            loadData();  
            return view;  
        }  
      
        @Override  
        protected void loadData() {  
            if(!isPrepared || !isVisible) {  
                return;  
            }  
            //填充各控件的数据  
        }  
      
    }  
    

    Fragment生命周期中,setUserVisbleHint先于onCreateView执行。上面实例中,当TabFragment可见时,先进入loadData方法,当判断各控件未初始化完毕,则进入onCreateView方法,当控件初始化完毕后,会再次调用loadData。在loadData中判断isPrepared和isVisible,只要有一个不为true就不往下执行。因此,只有初始化完成并且fragment可见情况下,才会加载数据,这样就避免了未初始化带来的问题。

    在这里感谢提供的帮助貌似掉线

    版权声明:本文为博主原创文章,未经博主允许不得转载。

    相关文章

      网友评论

      • DevCW:这种方法并不靠谱,漏洞比较多。
        首先,你的View加载完成了吗? loadData之后操作UI,有一定可能是报NullPointerExeception的吧!
        其次, setVisibleToUser并不适用所有情况, 只有在FragmentPagerAdapter配合下才会生效,其他是不走这个的。
      • 戴定康:这种方式并不推荐,没有考虑到此时view是否加载完毕
      • 那又怎么样_c46f:setUserVisibleHint 这个方法就没走啊!!!
      • SiberianDante:代码原封不动的复制粘贴啊大哥
      • 桂林的小河:小弟不才 推荐一个我的文章,懒加载相关的:http://www.jianshu.com/p/092418c5fe7f :smile:
      • CROAD:不错噢,能对viewPager 实现懒加载吗
      • 0f69314fd625:在basefragment中的public boolean isPrepared = false;感觉把public该成protect比较好,或者是在TabFragment中privateboolean isPrepared。
      • 52599a6b3597:不可以啊,,当Fragment可见时不执行loadData方法了,
        涂壶:真的,当Fragment可见时不执行loadData方法了
        于阗:再看看代码有没有哪里没写对
      • f71630e28ab3:分享的很好~~ :smile:
      • ff6741cb3c19:三个地方的单词拼写错了,visible 不是visable
        于阗:@汗仑尔  :grin: 谢谢指正

      本文标题:Android之Fragment懒加载分析

      本文链接:https://www.haomeiwen.com/subject/ivmkjttx.html