Android杂谈(15)关于ViewPager里的Fragment的生命周期+懒加载

来源:互联网 发布:mac夜神模拟器 机型 编辑:程序博客网 时间:2024/06/15 21:28


转载请注意:http://blog.csdn.net/wjzj000/article/details/52623819

本菜GitHub上开源了一个小的Android项目,感兴趣的看官大大们可以star下:

https://github.com/zhiaixinyang/MyFirstApp



最近写了一个小项目,发现一个小问题。(下文有关于懒加载的补充)

  • 事情的经过是这样的......ViewPager中有四个Fragment,当滑动到第3个Fragment时第4个Fragment的一些方法被执行。
  • 所以这里就测试并记录一下ViewPager中的Fragment的生命周期的调用情况。

测试Demo中ViewPager中有四个Fragment,分别对应OneFragment-Two...-Three...-Four...

下图是程序启动时的情况:OneFramgnet的onAttach首先被调用,紧接着是onCreate;然后就成为了TwoFramgnet的onAttach和onCreate被调用。

之后才是OneFragment的onCreateView和onViewCreated以及onActivityCreated被调用...

当滑动到第2个Fragment时,也就是当前显示为TwoFragment,如下的方法被调用。


当滑动到第3个Fragment时,也就是当前显示为ThreeFragment,如下的方法被调用;

可以看到在这里和上边那种情况很类似。


当滑到第4个Fragment时会发现什么方法也未调用。也就是说滑动时,会提前把下一个Fragment加载出来。那么如果我们往前滑动会出现什么情况呢?

当我回滑动到ThreeFragment时,调用情况如下:


仅仅执行了TwoFragment里的相关生命周期的调用,而需要显示的ThreeFragment中的生命周期并未被调用。而是直接显示出来

再往前滑动一次,也就是TwoFragment,调用如下:


同样,是执行了OneFragment的生命周期,TwoFragment的任何方法都没有执行。

我相信,此时都多多少少有点自己那种只可意会不可言传的感觉了....(我只是不知道该如何总结而已)


Google为了让ViewPager能够更流畅的使用,所以提前进行相关方法的调用。如果不想这样。那么就要使用懒加载。其实就是自己根据业务逻辑重新写一下生命周期。的方法。

Fragment的基础应用:http://blog.csdn.net/wjzj000/article/details/51879798


2016年12月6日补充Fragment懒加载:

上文中我们分析了,缓存Fragment作用是为了使ViewPager的滑动更为流畅。但是有时提前加载会发生我们不愿意看到的事情,所以懒加载在一定的场合之下是有特定的应用范围的。

  • 懒加载的核心是重写这个方法:setUserVisibleHint(boolean isVisibleToUser)


关于此方法的官方API:

setUserVisibleHint    在API级别15中添加    void setUserVisibleHint(boolean isVisibleToUser)

向系统提示此fragment的UI是否对用户当前可见。 此提示默认为true,并且跨fragment实例状态保存和恢复是持久的。

应用可以将其设置为false,以指示fragment的UI滚动到可见性之外或者用户不能直接看到。 这可以由系统使用以对诸如fragment生命周期更新或加载器排序行为的操作进行优先级排序。

注意:在Android N之前,有一个平台错误,可能会导致setUserVisibleHint在FragmentTransaction提交之前将fragment带到启动状态。 由于某些应用程式依赖此行为,因此会将宣告targetSdkVersion为23或以下的应用程式保留。


先让我们仔细看一下下面打印的Log日志,不要关注onFirstUserVisible方法(这是自己写的...)

我们可以看到一个问题,那就是第二个TwoFragment的setUserVisibleHint没有再次出现true的情况。也就是说,当我们只有滑动到TwoFragment的时候,它的setUserVisibleHint才会为true。

  • 可能此时有朋友会问这有什么用吗?它的其他方法都已经被调用了。怎么再懒加载?我最初也是有这个疑问...没错我们正常思路的确是在onCreateView啊或是onViewCreate中进行一个初始化的操作。这样的确会造成多个Fragment同时加载的情况。但是...我们有了setUserVisibleHint这个方法控制后,我们可以通过抽象方法,在setUserVisibleHint中通过true/false完成对相关的抽象方法的调用。

test: com.example.mbenben.myapplication.OneFragment:setUserVisibleHint:false
test: com.example.mbenben.myapplication.TwoFragment:setUserVisibleHint:false
test: com.example.mbenben.myapplication.OneFragment:setUserVisibleHint:true
test: com.example.mbenben.myapplication.OneFragment:onCreateView
test: com.example.mbenben.myapplication.OneFragment:onActivityCreated
test: com.example.mbenben.myapplication.OneFragment:onFirstUserVisible
test: com.example.mbenben.myapplication.TwoFragment:onCreateView
test: com.example.mbenben.myapplication.TwoFragment:onActivityCreated

这是网络中颇受好评的写法:(相关注释已写入)

private boolean isFirstVisible = true;    private boolean isFirstInvisible = true;    private boolean isPrepared;    @Override    public void onActivityCreated(Bundle savedInstanceState) {        super.onActivityCreated(savedInstanceState);        initPrepare();    }    private synchronized void initPrepare() {        if (isPrepared) {            onFirstUserVisible();        } else {            isPrepared = true;        }    }    //我们主要捋一下这个方法的过程    @Override    public void setUserVisibleHint(boolean isVisibleToUser) {        super.setUserVisibleHint(isVisibleToUser);        //首先此处的判断,很明显,当滑动到此Fragment是即为true        if (isVisibleToUser) {            /**             * 此判断作用就是它名字的直译:是否为第一次可见             * 此处调用只需要加载一次的方法...             */            if (isFirstVisible) {                isFirstVisible = false;                /**                 * initPrepare()之中调用的是onFirstUserVisible()                 * 相关数据的初始化就可以写于此                 */                initPrepare();            } else {                //此方法的作用是调用一些每次Fragment可见后都要执行的方法                onUserVisible();            }        } else {            if (isFirstInvisible) {                isFirstInvisible = false;                onFirstUserInvisible();            } else {                onUserInvisible();            }        }    }    protected abstract void onFirstUserVisible();    protected abstract void onUserVisible();    private void onFirstUserInvisible() { }    protected abstract void onUserInvisible();

OK,关于懒加载的内容补充到此就结束了。


0 0