ViewPagerIndicator源码解读

来源:互联网 发布:开源php cms 编辑:程序博客网 时间:2024/06/07 02:39

ViewPagerIndicator源码解读

1.TabMainActivity最先执行,而且在Adapter里new了FirstLayerFragment因为FirstLayerFragment继承LazyFragment,LazyFragment继承BaseFragment,BaseFragment继承Fragment,现在继续看执行哪里
2.主要是区分setUserVisibleHint和onCreateView这两个方法的先后顺序。先执行setUserVisibleHint方法,而代码中却有如下判断
public void setUserVisibleHint(boolean isVisibleToUser) {    super.setUserVisibleHint(isVisibleToUser);    if (isVisibleToUser && !isInit && getContentView() != null) {        //没有初始化才会走这里。而且不是说setUserVisibleHint方法比初始化方法前面执行吗,为什么首页没有执行这里        //因为getContentView()==null不符合条件        Log.d("xiao", "这个时候不是首页在这里加载数据");        isInit = true;        onCreateViewLazy(savedInstanceState);        onResumeLazy();    }    if (isInit && getContentView() != null) {//如果初始化过了,才会走这里        if (isVisibleToUser) {            Log.d("xiao2", "初始化过了走这里");            isStart = true;            onFragmentStartLazy();        } else {            Log.d("xiao22", "初始化过了走这里");            isStart = false;            onFragmentStopLazy();        }    }}
,首页满足前面两个条件但是首页并没有setContentView所以首页的setUserVisibleHint方法因为不符合条件并没有执行完全,所以首页是没走完setUserVisibleHint却走完了onCreateView方法,看下onCreateView代码首页执行如下:
if (getUserVisibleHint() && !isInit) {//如果fragment中的UI已经可见,而且初始化为false    //所以划到哪个fragment才会加载一次这个fragment,但是为什么会执行两次。和上面问题一样翻倍了    //初始化时,只有index=0的fragment才会执行这里,且会执行两次。    Log.d("xiao11", "这个时候isInit==" + isInit + "且getUserVisibleHint()==" +            getUserVisibleHint());    isInit = true;//则将初始化改为true    //这个地方执行onCreateViewLazy方法,是专门为首页服务的(也可以说是为第一个展示在屏幕上的fragment服务的)    onCreateViewLazy(savedInstanceState);//在子Fragment中执行创建lazyView的方法,    //只有在这里才会执行onCreateViewLazy方法,加载数据,首页数据在这里加载,那么不是首页数据在哪里加载呢?} 
易知此时,做了两件事。一,把isInit赋值为true;二,执行onCreateViewLazy方法加载了首页数据。
那么非首页的fragment呢?此时也会先执行setUserVisibleHint后执行onCreateView方法。由上面代码可知,非首页显然不满足isVisibleToUser这个条件,因为非首页这个时候都是不可见的。所以非首页也是没有压根就没有执行setUserVisibleHint方法,而是继续执行onCreateView方法。继续看onCreateView代码:
else {//如果没有同时满足fragment中的UI已经可见和初始化为false    //初始化时,其他三个没有划到的fragment会执行这里,且会执行两次    //这个时候不执行加载数据的逻辑,只是弄一个预加载的页面弄上去    //这个时候还是都没有进行初始化的,isInit==false    Log.d("xiao12", "这个时候isInit==" + isInit + "且getUserVisibleHint()==" +            getUserVisibleHint());    LayoutInflater layoutInflater = inflater;    if (layoutInflater == null) {        layoutInflater = LayoutInflater.from(getApplicationContext());    }    layout = new FrameLayout(layoutInflater.getContext());//那么首先创建一个新的FrameLayout控件    View view = getPreviewLayout(layoutInflater, layout);    if (view != null) {        layout.addView(view);    }    layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams            .MATCH_PARENT));    super.setContentView(layout);//这个是为了设置预加载页面,终于知道这玩意有啥用了,为了区分    //首页和非首页的。因为首页没有setContentView,所以不会执行setUserVisibleHint里的onCreateViewLazy}
这个时候由于不满足getUserVisibleHint()这个条件,所以非首页在onCreateView方法中执行以上代码,目的是为了给非首页的fragment加一个contentview。
3.接下来分析,滑动fragment页面会怎么执行代码。这个阶段已经过了初始化的阶段了,即onCreateView方法不会再执行了。但是setUserVisibleHint()方法还是会执行,为什么呢?请看代码注释翻译为中文就是当碎片对于用户可见时通知系统,所以还是会执行。看上面代码,
注意这个时候fragment的条件是:1.可见了;2.还有没有进行初始化(因为这个时候只有首页进行了初始化);3.getContentView也不会空;
所以综上三个条件,此时满足if条件,且将isInit赋值true,并执行加载数据方法onCreateViewLazy()。
4.现在又有一个问题,就是setUserVisibleHint()方法会滑一个fragment就执行一次,那就会重复加载数据。这个时候isInit布尔值就起作用了,纵观代码发现isInit=true;总是伴随着onCreateViewLazy()同时出现,所以只要if(!isInit)就可以防止重复加载了。
总结:
LazyFragment通过三个boolean值分别是isInit、isVisibleToUser、getContentView() != null完美解决了两个问题:
1.初始化阶段,阻止了先执行setUserVisibleHint()方法,主要是里面的onCreateViewLazy()加载数据的方法,让onCreateView方法优先执行;
2.通过isInit布尔值,防止重复执行onCreateViewLazy()方法,重复加载数据;
if (!isEnabled() || mReturningToStart || canChildScrollUp()        || mRefreshing || mNestedScrollInProgress) {    // Fail fast if we're not in a state where a swipe is possible    return false;}
0 0