友盟页面统计 - 关于Viewpager中的Fragment的生命周期
Activity和Fragment各自理论上的生命周期
- Activity的生命周期是较为经典也最清晰的,在此不表;
- Fragment从出现到广泛运用也有一段时间了,其标准生命周期也仅比Activity多出一些流程,如onCreateView();
- Activity和Fragment在实际编码中必定是结合出现的,表现为Activity作为容器,装载有一个或若干个Fragment;
- 装载多个Fragment时,经常使用TabHost和Viewpager作为载体;
- 在实际编码中发现,Activity和Fragment的混合情况里,其生命周期的交叉可能与预想中有差别;
使用如下方式加载Fragment时:
- getSupportFragmentManager()
- .beginTransaction()
- .add(R.id.fragment_container, mFragment, SHARE_PUBLIC_LIST_FRAGMENT_TAG)
- .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()方法本身很接近我们的需求,它的局限点我采取了一个侵入式的解决方式:
- protected boolean isCreated = false;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // ...
- isCreated = true;
- }
- /**
- * 此方法目前仅适用于标示ViewPager中的Fragment是否真实可见
- * For 友盟统计的页面线性不交叉统计需求
- */
- @Override
- public void setUserVisibleHint(boolean isVisibleToUser) {
- super.setUserVisibleHint(isVisibleToUser);
- if (!isCreated) {
- return;
- }
- if (isVisibleToUser) {
- umengPageStart();
- }else {
- umengPageEnd();
- }
- }
对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的生命周期的更多相关文章
- iOS之友盟错误统计解决
http://www.cocoachina.com/ios/20150720/12627.html http://lieyunye.github.io/blog/2013/09/10/how-to-a ...
- 【转】WPF中的窗口的生命周期
原文地址:http://www.cnblogs.com/Jennifer/articles/1997763.html WPF中的窗口的生命周期 WPF中所有窗口的基类型都是System.Windows ...
- Envoy 代理中的请求的生命周期
Envoy 代理中的请求的生命周期 翻译自Envoy官方文档. 目录 Envoy 代理中的请求的生命周期 术语 网络拓扑 配置 高层架构 请求流 总览 1.Listener TCP连接的接收 2.监听 ...
- vue生命周期图示中英文版Vue实例生命周期钩子
vue生命周期图示中英文版Vue实例生命周期钩子知乎上近日有人发起了一个 “react 是不是比 vue 牛皮,为什么?” 的问题,Vue.js 作者尤雨溪12月4日正面回应了该问题.以下是尤雨溪回复 ...
- React Native 中的component 的生命周期
React Native中的component跟Android中的activity,fragment等一样,存在生命周期,下面先给出component的生命周期图 getDefaultProps ob ...
- spring-第八篇之容器中的bean的生命周期
1.容器中的bean的生命周期 spring容器可以管理singleton作用域的bean的生命周期,包括bean何时被创建.何时初始化完成.何时被销毁.客户端代码不能控制该类型bean的销毁.spr ...
- 动态更新ViewPager中的Fragment(替换Fragment)
1.最近做需求,遇到一个问题,一个Fragment中包含了一个ViewPager,viewPager中包含一adapter ,adapter中包含了4个Fragment.想要动态替换第3个Fragme ...
- ionic中关于ionicView 的生命周期
当我们来回切换页面时候,视图被缓存下来,不用每次再去new一个新的视图,可以大大地提高性能.当跳出一个视图后,视图的元素被保存在DOM中,它的作用域也就不在$watch的作用域内,当我们访问一个已经被 ...
- Android中静态变量的生命周期
静态变量的生命周期,起始于类的加载,终止于类的释放.什么时候类会加载呢?我们知道,在app打开时,会创建一个进程,然后初始化一个dvm的实例,负责类的加载释放 和 垃圾回收等.换句话说,在进程创建之后 ...
随机推荐
- python之集合,函数,装饰器
本节主要内容如下: 1. set集合 2. 函数 -- 自定义函数 -- 内置函数 3. 装饰器 一. set 集合: 一个无序且不重复的序列. tuple算是list和str的杂合(杂交的都有自己的 ...
- [第三方]AFNetWorking3.0网络框架使用方法
官网地址https://github.com/AFNetworking/AFNetworking #import <AFNetworking.h> - (void)viewDidLoad ...
- ant使用指南详细入门教程
这篇文章主要介绍了ant使用指南详细入门教程,本文详细的讲解了安装.验证安装.使用方法.使用实例.ant命令等内容,需要的朋友可以参考下 一.概述 ant 是一个将软件编译.测试.部署等步骤联系在一起 ...
- 批处理命令——goto 和 :
谈起goto,相信大家应该想到的是面向过程编程.其实,这就相当于当有人向你谈起class,意味着你就懂得面向对象编程.如果你不懂,那么你们的沟通将会很困难.不懂我说的啥意思吗?请参见曾经分享王路的一篇 ...
- 最牛逼android上的图表库MpChart(二) 折线图
最牛逼android上的图表库MpChart二 折线图 MpChart折线图介绍 MpChart折线图实例 MpChart效果 最牛逼android上的图表库MpChart(二) 折线图 最近工作中, ...
- 【python】mysqlDB转xml中的编码问题
背景:有mysql数据库,将数据从数据库中读取,并存储到xml中 采用了MySQLdb和lxml两个库 具体编码处理过程如下: . 指定mysql的编码方式 .取数据库data->判断data类 ...
- php面向对象中的静态与抽象,接口
静态又包括: 普通成员: 普通成员是属于对象的 静态成员: 静态成员是属于类的 关键字:static self关键字:在类里面代表该类,前面不用加$ 在静态方法里面不能调用普通成员 在普通方法里面能够 ...
- python基础——继承和多态
python基础——继承和多态 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类 ...
- php基础面试题1
问题1:谈谈你对的PHP的基本认识. 回答:PHP是Hypertext Preprocessor(超文本预处理器)的简称,是一种用来开发动态网站的服务器端脚本语言. 问题2:什么是MVC? 回答:MV ...
- 用spring+hibernate+struts 项目记录以及常用的用法进等
一.hibernate1. -----BaseDao------ // 容器注入 private SessionFactory sessionFactory; public void setSessi ...