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. ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083)-POJ1270)

    两道经典的同类型拓扑排序+DFS问题,第二题较第一题简单,其中的难点在于字典序输出+建立单向无环图,另外理解题意是最难的难点,没有之一... POJ1128(ZOJ1083)-Frame Stacki ...

  2. 7.js模式-装饰者模式

    1. 装饰者模式 给对象动态增加职责的方式称为装饰者模式. Function.prototype.before = function(beforefn){ var _self = this; retu ...

  3. FFmpeg-20160418-snapshot-bin

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

  4. java Thread和Runnable区别

    ①Thread类实现了Runnable接口,主要构造方法为Thread(Runnable target).Thread(Runnable target,String name).Thread(Stri ...

  5. [Android]drawable-nodpi文件夹 的作用

    把一些不能被拉伸的图片放在 drawable-nodpi 中,此图片将不会被放大,以原大小显示. 看下图: 这两个图片被放到了drawable-nodpi 中 在不同分辨率下的显示大小是一样的,不会被 ...

  6. 比较两个mysql数据库表结构的差异

    需求来源:一个线上系统,一个开发系统,现在要把开发系统更新到线上,但是开发系统的数据库结构与线上的略有差异,所以需要找出两个数据库的表结构差异. 数据库表结构的差异 注:操作均在Linux系统下完成 ...

  7. AFNetWorking支持解析html的方法

    在AFURLResponseSeriallzation.m的226行 手动添加@"text/html" 添加之前解锁文件

  8. MyEclipse8.5可用注册码(到2018年)

    转载自:http://blog.csdn.net/z123252520/article/details/45873159 Subscriber:zy Subscriber Code:mLR8ZC-85 ...

  9. 字符串与byte数组转换

    string weclome=""; byte[] data = new byte[1024]; //字符串转byte数组 data = Encoding.ASCII.GetByt ...

  10. CodeForces 407B Long Path (DP)

    题目链接 题意:一共n+1个房间,一个人从1走到n+1,如果第奇数次走到房间i,会退回到房间Pi,如果偶数次走到房间i,则走到房间i+1,问走到n+1需要多少步,结果对1e9+7取模. 题解:设dp[ ...