这个情况仅适合与多个fragment之间切换时统计,而非activity和fragment同时交互,因当时项目为首页4个fargment时长统计,因此适合,经下面网友评论指出,特在这里写出此问题,因最近项目较忙,具体情况以后验证后会发出博文更新。

现在越来越多的应用会使用viewpager+fragment显示自己的内容页,fragment和activity有很多共同点,如下图就是fragment的生命周期

但是fragment和activity不同的是当调用本身的onResume和onPause方法的时候可能并不是当前的fragment在显示,例如当加载下面这张图时,当我打开MainActivity时显示的是第一个fragment 但此时调用的方法步骤如下:

08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onAttach
08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreate
08-11 11:33:36.159    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onResume()
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onAttach
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreate
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated

08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onResume()   可见此时虽然用户看到的是第一个fragment 但第二个fragment onAttech onCreate

onCreateView onActivityCreater onStart(“这个我没油打印log”)onResume 方法已经调用,这会导致如果我们要统计用户更喜欢哪个fragment的内容时,虽然fragment已经创建并且onResume但其实并没有显示这一页,那么是什么原因呢,这是因为android v4包下的viewpager,为了让用户在切换过程中不会卡顿,谷歌官方默认当创建第一个fragment方法时回创建第二个fragment以确保用户滑动时第二个view已经被创建,保持viewPager的平滑滑动效果。

翻阅谷歌api发现viewpager有一个方法即 setOffscreenPageLimit。但当在viewpager设置以下代码

viewPager.setOffscreenPageLimit();

运行时打印的log和上面完全一致,即就算你设置只加载一个fragment还是会加载第二个fragment,原因是setOffscreenPageLimit中的源码时这样写的

public void setOffscreenPageLimit(int limit) {
if (limit < DEFAULT_OFFSCREEN_PAGES) {
Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
DEFAULT_OFFSCREEN_PAGES);
limit = DEFAULT_OFFSCREEN_PAGES;
}
if (limit != mOffscreenPageLimit) {
mOffscreenPageLimit = limit;
populate();
}
}

这个 DEFAULT_OFFSCREEN_PAGES 定义如下 private static final intDEFAULT_OFFSCREEN_PAGES= 1;

就是如果你设置为0 也没用。!!!

为了解决判断是否fragment当前显示问题 可以在fragment重写 setUserVisibleHint(boolean isVisibleToUser)

在fragment添加log日志

public class Fragment1 extends Fragment {
private static final String TAG = "Fragment1"; @Override
public void onAttach(Activity activity) {
super.onAttach(activity);
L.v(TAG, "onAttach");
} @Override
public void setUserVisibleHint(boolean isVisibleToUser) {
L.v(TAG, "setUserVisibleHint " + isVisibleToUser);
} @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
L.v(TAG, "onCreate");
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
L.v(TAG, "onCreateView");
View view = inflater.inflate(R.layout.fragment_layout,null);
TextView tv = (TextView) view.findViewById(R.id.tv1);
tv.setText(TAG);
return view;
} @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
L.v(TAG,"onActivityCreated");
} @Override
public void onResume() {
super.onResume();
L.v(TAG, "onResume()");
} @Override
public void onPause() {
super.onPause();
L.v(TAG,"onPause");
} @Override
public void onStop() {
super.onStop();
L.v(TAG,"onStop");
}

启动activity打印日志如下:

08-11 11:33:36.156    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-11 11:33:36.156    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
08-11 11:33:36.157    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true
08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onAttach
08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreate
08-11 11:33:36.159    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onResume()
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onAttach
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreate
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onResume()

当切换到第二个fragment时打印日志:

08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ setUserVisibleHint false
08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint true
08-11 11:33:54.084    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onAttach
08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onCreate
08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onCreateView
08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onActivityCreated
08-11 11:33:54.085    7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onResume()

可见当fragment显示时回调用方法 setUserVisibleHint中的isVisibleToUser = true 当fragment被切换隐藏时回 isVisibleToUser = false;

所以当我们要统计是否用户看到一个fragment时可以执行一下代码

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
L.v(TAG, "setUserVisibleHint " + isVisibleToUser);
if (isVisibleToUser) {
//统计代码 或者 fragment显示操作
} else { }
}

同时根据这个方法还可以进行数据的延迟加载,后面再写。

今天又看了一下发现单纯的执行上面的代码是有问题的,因为如果我们在else中认为用户是离开界面其实是不对的,因为根据启动第一个Fragment的log日志

08-11 11:33:36.156    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-11 11:33:36.156    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
08-11 11:33:36.157    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true
08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onAttach
08-11 11:33:36.158    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreate
08-11 11:33:36.159    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onResume()
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onAttach
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreate
08-11 11:33:36.160    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
08-11 11:33:36.161    7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onResume()

第一次setUserVisibleHint 方法 isVisibleToUser 是false 但其实这个时候只是还未初始化,并不是用户已经浏览界面准备离开,于是这里我们需要一个辅助标记变量具体代码如下:

/**
* 判断是否是初始化Fragment
*/
private boolean hasStarted = false;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
L.v(TAG, "setUserVisibleHint " + isVisibleToUser);
if (isVisibleToUser) {
hasStarted = true;
L.v(TAG,"开始界面");
} else {
if (hasStarted) {
hasStarted = false;
L.v(TAG,"结束界面");
}
}
}

当我们启动MainActivity时 Log打印如下:

08-13 17:55:45.850  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-13 17:55:45.850  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
08-13 17:55:45.850  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onAttach
08-13 17:55:45.850  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onCreate
08-13 17:55:45.850  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true
08-13 17:55:45.860  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ 开始界面
08-13 17:55:45.860  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
08-13 17:55:45.870  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onResume()
08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onAttach
08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onCreate
08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
08-13 17:55:45.880  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onResume()

切换到第二个fragment时,此时离开第一个fagment  log打印如下

08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ setUserVisibleHint false
08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ 结束界面
08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint true
08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ 开始界面
08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onAttach
08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onCreate
08-13 17:57:04.310  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onCreateView
08-13 17:57:04.320  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onActivityCreated
08-13 17:57:04.320  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onResume()

切换到第三个fragment时,此时离开第二个fragment log打印如下:

08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment2﹕ 结束界面
08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ setUserVisibleHint true
08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment3﹕ 开始界面
08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onPause
08-13 17:58:15.040  21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onStop

可见这样就可以准确统计用户是否离开或者开始浏览界面了。根据这些开始和离开可以统计用户停留界面的时间等数据。

Android setUserVisibleHint-- fragment真正的onResume和onPause方法的更多相关文章

  1. setUserVisibleHint-- fragment真正的onResume和onPause方法

    现在越来越多的应用会使用viewpager+fragment显示自己的内容页,fragment和activity有很多共同点,如下图就是fragment的生命周期 但是fragment和activit ...

  2. setUserVisibleHint-- fragment真正的onResume和onPause方法

    现在越来越多的应用会使用viewpager+fragment显示自己的内容页,fragment和activity有很多共同点,如下图就是fragment的生命周期 但是fragment和activit ...

  3. Android Fragment真正意义上的onResume和onPause

    Fragment虽然有onResume和onPause的,但是这两个方法是Activity的方法,调用时机也是与Activity相同,和ViewPager搭配使用这个方法就很鸡肋了,根本不是你想要的效 ...

  4. 【Android】Fragment真正意义上的onResume和onPause

    前言 Fragment虽然有onResume和onPause的,但是这两个方法是Activity的方法,调用时机也是与Activity相同,和ViewPager搭配使用这个方法就很鸡肋了,根本不是你想 ...

  5. Fragment的可见再载入的方法(真正的Fragment的OnResume和OnPause)

    一 起因 我们在做应用的过程中,一个应用的界面可能是多个Fragment切换而成的.可是如果在每次应用启动的时候就去载入大量的网络数据(如果你的每一个Fragment都须要载入网络数据.你也能够理解为 ...

  6. Android Activity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?

    原文:http://www.xuebuyuan.com/1608083.html 最近在研究Activity的启动流程,老罗的blog在看,也找了其它资料学习,也跟过Android4.3的源码, 在跟 ...

  7. Android fragment切换后onresume时报 Attempt to write to field 'int android.support.v4.app.Fragment.mNextAnim'

    动态加载fragment以后,调用了remove方法移除Fragment,在返回来的时候报 Attempt to write to field 'int android.support.v4.app. ...

  8. 重温Android和Fragment生命周期

    重温下Android和Fragment生命周期,理解生命周期方法的作用,什么时候调用,可以做一些什么操作. 1.Android生命周期 1.1 生命周期图 1.2 生命周期函数说明 onCreate: ...

  9. android之Fragment基础详解(一)

      一.Fragment的设计哲学 Android在3.0中引入了fragments的概念,主要目的是用在大屏幕设备上--例如平板电脑上,支持更加动态和灵活的UI设计.平板电脑的屏幕比手机的大得多,有 ...

随机推荐

  1. luogu2948 滑雪课

    题解里面全是dp的大神本蒟蒻瑟瑟发抖奉上一篇记忆化搜索... 其实嘛,记忆化搜索还是很安全透彻清真人品的,一般递推不好实现dp可以用记忆化搜索 然后本题先预处理一个mint[i]代表当前能力值为i,参 ...

  2. JEECG入门

    姓名:陈中娇    班级:软件151 1.准备: 下载Jdk1.6+.myeclipse.tomcat6.0.MySQL数据库.jeecg-framework压缩包 2.安装:①.安装jdk,配置好环 ...

  3. java8 optional操作

    目标:测试option的过滤,链式操作: 代码: package test; import java.util.ArrayList; import java.util.Arrays; import j ...

  4. python 字符串 操作

    去空格及特殊符号 s.strip().lstrip().rstrip(',') 复制字符串 #strcpy(sStr1,sStr2) sStr1 = 'strcpy' sStr2 = sStr1 sS ...

  5. C语言的存储类别和动态内存分配

    存储类别分三大类: 静态存储类别 自动存储类别 动态分配内存 变量.对象--->内存管理 内存考虑效率(时间更短.空间更小) 作用域 链接.---->空间 存储器   ----->时 ...

  6. sharepoint_study_9

    描述:sharepoint2013 网站修改导航条标题 SuiteBartext 图示: 解决: 管理员身份进sharepoint powershell ,依次敲入搞定1. $app = Get-SP ...

  7. bios-----> grub

    系统有两块硬盘, 第一块安装的win7, 第二块安装ubuntu 默认从sda加载grub 如果在bios页面选择从sdb启动,会找不到grub 进入原来的sda系统,  grub-install / ...

  8. Outlook 2010中263邮箱客户端设置

    Outlook 2010中263邮箱客户端设置 1.首次添加电子邮箱账户:打开outlook,在账户设置和服务中分别选择:“手动配置服务器设置或其他服务器类型”,“Internet电子邮件” 2.在i ...

  9. Problem06 求最大公约数及最小公倍数

    题目:输入两个正整数m和n,求其最大公约数(m,n)和最小公倍数[m,n]. 程序分析:利用辗转相除法. 利用辗除法:用较大数除以较小数,再用出现的余数(第一余数)去除除数, 再用出现的余数(第二余数 ...

  10. apply,call,bind

    /*apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向): 如果使用apply或call方法,那么this指向他们的第一个参数,apply的第二个参数是 ...