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. python pexpect 学习与探索

    pexpect是python交互模块,有两种使用方法,一种是函数:run另外一种是spawn类 1.pexpect  module 安装 pexpect属于第三方的,所以需要安装, 目前的版本是 3. ...

  2. ALV 输入数据时数字缩小一千倍的问题解决

    这个字段后面有三位小数  我输入 1 一回车 就变成了0.001 了 解决方法 DATA: wa_fieldcatalog    TYPE lvc_s_fcat,    "显示数据列内表工作 ...

  3. iOS AES加密解密实现方法

    使用方法 先导入头文件 #import "NSData+AES.h" //AES测试 //用来密钥 NSString *key = "; //用来发送的原始数据 NSSt ...

  4. Effective C++ -----条款31:将文件间的编译依存关系降至最低

    支持“编译依存性最小化”的一般构想是:相依于声明式,不要相依于定义式.基于此构想的两个手段是Handle classes 和 Interface classes. 程序库头文件应该以“完全且仅有声明式 ...

  5. JavaScript高级程序设计学习笔记--面向对象程序设计

    工厂模式 虽然Object构造函数或对象字面量都可以用来创建单个对象,但这些方式有个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码.为解决这个问题,人们开始使用 工厂模式的一种变体. f ...

  6. ExpandableListView的用法

    ExpandableListView组件是android中一个比较常用的组件,当点击一个父item的时候可以将它的子item显示出来,像手机QQ中的好友列表就是实现的类型效果.使用Expandable ...

  7. 'XCTest/XCTest.h' file not found

    直接写解决方法吧:在报错的 Target 中的 Building Settings 中 Framework Search Paths 里面添加 $(PLATFORM_DIR)/Developer/Li ...

  8. [转]c++ vector 遍历方式

    挺有趣的,转来记录 随着C++11标准的出现,C++标准添加了许多有用的特性,C++代码的写法也有比较多的变化.   vector是经常要使用到的std组件,对于vector的遍历,本文罗列了若干种写 ...

  9. JDK、Jmeter、Android环境变量配置

    JDK环境变量 1.在系统变量里点击新建,变量名填写JAVA_HOME,变量值填写JDK的安装路径,在这里就填写"D:\Program Files\Java\jdk1.6.0_26" ...

  10. iptables下state的4种形式

    ESTABLISHED,NEW,RELATED,INVALID. 注意:TCP/IP 标准描述下,UDP及ICPM数据包是没有连接状态的,但在state模块的描述下,任何数据包都有连接状态. ESTA ...