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. MySQL 5.6 my.cnf 模版

    [client] port = socket = /var/run/mysqld/mysqld.sock [mysqld_safe] thp-setting=never socket = /var/r ...

  2. Greedy:Sum of Consecutive Prime Numbers(POJ 2739)

     素数之和 题目大意:一些整数可以表示成一个连续素数之和,给定一个整数要你找出可以表示这一个整数的连续整数序列的个数 方法:打表,然后用游标卡尺法即可 #include <iostream> ...

  3. 后台session过期,tomcat重启,自动跳转页面js写法

    if (window != top) { //top.location.href = location.href;//因为系统分为普通用户和后台,所以暂时写死 if(top.location.href ...

  4. 【Git】笔记5 分支管理2

    来源:廖雪峰 通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息. 如果要强制禁用Fast forward模式,Git就会在merge时生成一 ...

  5. LeetCode 453 Minimum Moves to Equal Array Elements

    Problem: Given a non-empty integer array of size n, find the minimum number of moves required to mak ...

  6. Windows Form 中快捷键设置

    在Windows Form程序中使用带下划线的快捷键只需要进行设置: 就能够工作.

  7. [Android Pro] Android下toolbox简介

    toolbox是Android 自带的提供shell命令的软件.有点类似于busybox,但功能上好像弱很多.其源码可以从Android source code 中system/core/toolbo ...

  8. 面向对象的小demo

    两个类如下 package cao.com.duixiang; import java.util.Arrays; public class OtherTest { //求max public int ...

  9. 从键盘输入成绩,找出最高分,并输出学生成绩等级。成绩>=最高分-10,为A,成绩>=最高分-20,为B,成绩>=最高分-30,为C,其余等级为D

    import java.util.Scanner;public class TestStudent { public static void main(String[] args) { //从键盘获得 ...

  10. oracle学习不错的网站

    http://oracle-base.com/articles/linux/rlwrap.php