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


转载请注意: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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值