Activity和Fragment各自理论上的生命周期

  • Activity的生命周期是较为经典也最清晰的,在此不表;
  • Fragment从出现到广泛运用也有一段时间了,其标准生命周期也仅比Activity多出一些流程,如onCreateView();

  • Activity和Fragment在实际编码中必定是结合出现的,表现为Activity作为容器,装载有一个或若干个Fragment;
  • 装载多个Fragment时,经常使用TabHost和Viewpager作为载体;
  • 在实际编码中发现,Activity和Fragment的混合情况里,其生命周期的交叉可能与预想中有差别;

  • 使用如下方式加载Fragment时:

     
    1. getSupportFragmentManager()
    2. .beginTransaction()
    3. .add(R.id.fragment_container, mFragment, SHARE_PUBLIC_LIST_FRAGMENT_TAG)
    4. .commitAllowingStateLoss();
    
    
     

    其onResume和onPause执行过程为:

    • Activity - onResume
    • Fragment - onResume
    • Activity - onPause
    • Fragment - onPause

友盟-页面统计要求

  • Activity和Fragment共同体页面统计中,需要保证线性不交叉,每个onPageStart都有一个onPageEnd配对,
  • 如:onPageStart ->onPageEnd-> onPageStart -> onPageEnd -> onPageStart ->onPageEnd
  • 这样才能保证每个页面统计的正确。

Viewpager中Fragment的生命周期

  • ViewPager装载Fragment一般使用FragmentPagerAdapter或FragmentStatePagerAdapter,同样借助FragmentManager,在adapter的getItem方法中根据position制定显示的fragment
  • 由于Viewpager的缓存特点,Viewpager启动时其第一个Fragment页面及待缓存的页面都将按顺序呢开始他们的正常生命周期,走向onResume,即:
    • Viewpager所在Activity - onResume
    • Fragment1 - onResume
    • Fragment2 - onResume
    • Fragment3 - onResume
  • 由于这若干个页面的生命周期被同时催化了,影响了我们的单一判断,即无法判断“真正”显示和消失在使用者眼前的页面。

解决方案

  • 方案1:设置Viewpager的缓存机制,不缓存除当前页以外的页面数据,所见即所得,离开即销毁;
  • 此方案对需求改动较大,且较影响用户体验;

  • 方案2:重载Fragment.onHiddenChanged(boolean hidden)方法,其参数hidden代表当前fragment显隐状态改变时,是否为隐藏状态,可通过check此参数作处理;
  • 此方案局限在于本方法的系统调用时间发生在显隐状态改变时,但第一次显示时此方法并不调用;

  • 方案3:重载Fragment.setUserVisibleHint(boolean isVisibleToUser)方法,其参数isVisibleToUser顾名思义最接近我们的需求,代表页面是否“真正”对使用者显示;
  • 此方案局限在于此方法的第一次系统调用甚至早于Fragment的onCreate方法,故其第一次调用时isVisibleToUser值总为false,影响我们对生命周期顺序的判定;
    • Fragment1 - isVisibleToUser - false (多余)
    • Fragment1 - isVisibleToUser - true
    • Fragment1 - isVisibleToUser - false
    • Fragment2 - isVisibleToUser - false (多余)
    • Fragment2 - isVisibleToUser - true
    • Fragment2 - isVisibleToUser - false

实际采用的解决方案

  • 根据对产品需求的理解和用户体验的统一,选择在方案3基础上加以改进;
  • setUserVisibleHint()方法本身很接近我们的需求,它的局限点我采取了一个侵入式的解决方式:

     
    1. protected boolean isCreated = false;
    2. @Override
    3. public void onCreate(Bundle savedInstanceState) {
    4. super.onCreate(savedInstanceState);
    5. // ...
    6. isCreated = true;
    7. }
    8. /**
    9. * 此方法目前仅适用于标示ViewPager中的Fragment是否真实可见
    10. * For 友盟统计的页面线性不交叉统计需求
    11. */
    12. @Override
    13. public void setUserVisibleHint(boolean isVisibleToUser) {
    14. super.setUserVisibleHint(isVisibleToUser);
    15. if (!isCreated) {
    16. return;
    17. }
    18. if (isVisibleToUser) {
    19. umengPageStart();
    20. }else {
    21. umengPageEnd();
    22. }
    23. }
    
    
     
  • 对onCreate方法结束的一个标记即可解决问题;

  • 切记:此标记的改变请勿放在Fragment的onActivtyCreate方法中,此方法调用滞后于setUserVisibleHint的判断

One more thing

  • Viewpager装载Fragment时还有另一个坑,Viewpager的父容器(Activity或Fragment)在显隐状态改变时,如在Activity的onResume和onPause调用时,并不会主动通知Viewpager内的Fragment执行其应用的生命周期,故我们需要再增加手动强制调用两次
  • 在Activity中查询到当前的Fragment,并执行其内方法,需要借助Viewpager,并改写其PagerAdapter;
  • 我采用了此文提到的Second Solution:如何获得ViewPager当前显示的Fragment?

友盟页面统计 - 关于Viewpager中的Fragment的生命周期的更多相关文章

  1. iOS之友盟错误统计解决

    http://www.cocoachina.com/ios/20150720/12627.html http://lieyunye.github.io/blog/2013/09/10/how-to-a ...

  2. 【转】WPF中的窗口的生命周期

    原文地址:http://www.cnblogs.com/Jennifer/articles/1997763.html WPF中的窗口的生命周期 WPF中所有窗口的基类型都是System.Windows ...

  3. Envoy 代理中的请求的生命周期

    Envoy 代理中的请求的生命周期 翻译自Envoy官方文档. 目录 Envoy 代理中的请求的生命周期 术语 网络拓扑 配置 高层架构 请求流 总览 1.Listener TCP连接的接收 2.监听 ...

  4. vue生命周期图示中英文版Vue实例生命周期钩子

    vue生命周期图示中英文版Vue实例生命周期钩子知乎上近日有人发起了一个 “react 是不是比 vue 牛皮,为什么?” 的问题,Vue.js 作者尤雨溪12月4日正面回应了该问题.以下是尤雨溪回复 ...

  5. React Native 中的component 的生命周期

    React Native中的component跟Android中的activity,fragment等一样,存在生命周期,下面先给出component的生命周期图 getDefaultProps ob ...

  6. spring-第八篇之容器中的bean的生命周期

    1.容器中的bean的生命周期 spring容器可以管理singleton作用域的bean的生命周期,包括bean何时被创建.何时初始化完成.何时被销毁.客户端代码不能控制该类型bean的销毁.spr ...

  7. 动态更新ViewPager中的Fragment(替换Fragment)

    1.最近做需求,遇到一个问题,一个Fragment中包含了一个ViewPager,viewPager中包含一adapter ,adapter中包含了4个Fragment.想要动态替换第3个Fragme ...

  8. ionic中关于ionicView 的生命周期

    当我们来回切换页面时候,视图被缓存下来,不用每次再去new一个新的视图,可以大大地提高性能.当跳出一个视图后,视图的元素被保存在DOM中,它的作用域也就不在$watch的作用域内,当我们访问一个已经被 ...

  9. Android中静态变量的生命周期

    静态变量的生命周期,起始于类的加载,终止于类的释放.什么时候类会加载呢?我们知道,在app打开时,会创建一个进程,然后初始化一个dvm的实例,负责类的加载释放 和 垃圾回收等.换句话说,在进程创建之后 ...

随机推荐

  1. FFmpeg-20160418-snapshot-bin

    ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 F ...

  2. Mathematics:Dead Fraction(POJ 1930)

    消失了的分式 题目大意:某个人在赶论文,需要把里面有些写成小数的数字化为分式,这些小数是无限循环小数(有理数),要你找对应的分母最小的那个分式(也就是从哪里开始循环并不知道). 一开始我也是蒙了,这尼 ...

  3. hdu 1002.A + B Problem II 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1002 题目意思:就是大整数加法. 两年几前做的,纯粹是整理下来的. #include <stdi ...

  4. [Android Pro] AES加密

    reference to :http://blog.csdn.net/wfung_kwok/article/details/7766427 package com.secufity.aes; impo ...

  5. 线程变量ThreadLocal的使用

    我们有时候会通过token进行多次查询(猪:token是redis中的key),比如: 一次是在登录拦截器中,一次是在controller的业务中查询,这样存在性能和资源的浪费问题!!! 那么如何将拦 ...

  6. strlen与sizeof

    strlen计算不包括终止符null字节的字符串长度,而sizeof则计算包括终止null字节的长度.另一个差别,strlen需要一次函数调用,而sizeof在编译时计算缓冲区长度.

  7. NYOJ题目11613n+1问题

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAscAAAIvCAIAAAAXg+GWAAAgAElEQVR4nO3dO1LryNsH4G8T5CyE2A ...

  8. jsp 过滤器 Filter 配置

    .如果要映射过滤应用程序中所有资源: <filter>    <filter-name>loggerfilter</filter-name>    <filt ...

  9. nfs 是Network File System 网络文件系统

    NFS的基本原刚是容许不同的客户端及服务通过一组PRC分享相同的文件系统,它是独立于操作系统,容许不同硬件及操作系统的系统共同进行文件的分享.NFS在文件传送过程中依赖于RPC协议.远程过程调用Rem ...

  10. 快速反编绎jar war包

    反编译这些class文件或jar包或war包,用TTools https://github.com/Supermax197/TTools [root@ok action]# tree /home/ok ...