一步步用懒加载Fragment实现ViewPager多级嵌套下的Fragment的显示与隐藏监听

一.需求背景

由于本猿在一个视频app开发组,有一个页面曝光埋点需求,用来统计界面曝光率与点击率,曝光埋点目的是运营为了统计节目曝光与被点击播放的比例,所以为了实现精准的统计数据,需要每个页面展示出来时才进行曝光数据上传,同时用户切换页面之后需要重新曝光,那么就需要监听到页面的显示与隐藏状态,而该视频app架构首页采用ViewPager与Fragment的多级嵌套,外层ViewPager采用FragmentPagerAdapter内层ViewPager采用FragmentStatePagerAdapter作为适配器(FragmentPagerAdapter与FragmentStatePagerAdapter区别,请自行百度),外层ViewPager会默认缓存相邻两个Fragment,而内层Viewpager也会默认缓存相邻两个Fragment,所以每次切换外层ViewPager将会创建多个内层Fragment,这个只是两级,如果三级嵌套呢?是不是很恐怖?如果每次埋点都放在Fragment的某一个生命周期里,是不是会有好很多的错误统计?那么问题来了:

1).哪个生命周期会只有Fragment页面真正可见与隐藏时才会执行?

a).看知道这里,肯定有人会说Fragment懒加载机制setUserVisibleHint()

利用Fragment的setUserVisibleHint()方法来进行监听Fragment可见性,没错,但是需要解决几个问题

  1. setUserVisibleHint一定会在onViewCreated()之前执行么?
  2. 最外层Fragment可以用setUserVisibleHint()进行监听,那么内层的Fragmen会乖乖的听话么,会单单只执行到某一个Fragment的setUserVisibleHint()么

答案自然都是否定的,下面感受一下被Fragments们支配的恐惧,看图中日志说话(图1是常规操作,图二为啥?)

图一图二3

图中每次点击打印的日志显示在底部,只打印了最底层的Fragment的setUserVisibleHint()与onViewCreated(),请仔细观察Fragment标题与底部日志变化,可以发现,

  1. 图一是初次创建,生命周期会按着setUserVisibleHint()->onCreate()->onCreateView()->onViewCreated()->on....执行
  2. 图二由于采用FragmentPagerAdapter保存了状态导致setUserVisibleHint()最后执行
  3. 每次点击并不会只执行单独某一个Fragment的setUserVisibleHint()
  4. onCreate()甚至不执行,其他生命周期为了显示,并没有打印出来,可以自己写个Demo测试下

b)还有人肯定会说,用Fragment的onHiddenChanged()

很遗憾,这个真不行,onHiddenChanged()方法调用前提是采用了Fragment的hide与show,来代替replace会保存每个Fragment实例

  1. hide与show这么用的在普通页面较少的app中是可行的
  2. 本猿参与的项目是视频app,页面较多,都保存下来,app内存占用是不是要炸啊

2).setUserVisibleHint真的一定会执行么

这个答案也是否定的,setUserVisibleHint只会因为与ViewPager一起使用,有预加载机制才会执行,Activity下单个Fragment只会走标准的生命周期

3).那么看着这么乱七八糟的一大堆生命周期,如何抽取出正在显示与隐藏的页面每次执行一个方法呢

很高兴真的可以抽取出来,看图说话,

丫的,牛逼!

无论点击下面或者上面的tab,都会只有一个Fragmnet执行消失方法一个执行显示方法,效果怎么样,你要是觉得很骚的话,不妨内心默默的说一声,“哎哟,不错哦”,哈哈哈

二.实现流程

1).定制基类BaseFragment

定制基类是常规操作,封装其他相关操作,每个人可以有不同封装,这里简单封装下BaseFragment.java

public abstract class BaseFragment extends Fragment {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
        @Nullable Bundle savedInstanceState) {
        if (getLayoutId() > 0) {
            View view = inflater.inflate(getLayoutId(), container, false);
            initView(view);
            return view;
        } else {
            return super.onCreateView(inflater, container, savedInstanceState);
        }
    }

    protected abstract void initView(View view);

    
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值