背景

最近在开发中遇到了一个问题。我们的app需要统计用户的页面路径,也就是用户使用各个页面的情况。这就需要在不同的页面跳入和跳出时记录下来。但是我们的app主要是由Fragment构成的。而在不同的使用情况下,判断Fragment是否可见的方法是不一样的。下面对这些不同的使用情况分开分析。

不同的情况

在Activity中直接使用

这种情况是最简单的,也就是在Activity使用XML引入,或者使用FragmentManager 的addFragment或者replaceFrament 动态载入。在这种情况下,只要监听Fragment的onResume和onPause方法就能够判断其显隐。在onResume和onPause中间是对用户可见的.

@Override
public void onResume() {
super.onResume();
//TODO now visible to user
}
@Override
public void onPause() {
super.onPause();
//TODO now invisible to user
}

使用show和hide来显隐的Fragment

FragmentManager除了addFragment和replaceFragment之外还有showFragment和hideFragment来做Fragment的显隐,这样可以提生页面切换的速度,是一种用空间换时间的方式。但是这样使用的Fragment在被hide的时候是不会调用onPause方法的。因为它只是在屏幕中不可见了,但是没有Pause。这时候我们需要监听onHiddenChanged方法

@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if(hidden){
//TODO now visible to user
} else {
//TODO now invisible to user
}
}

但是我们需要注意一点,那就是,如果用户直接按home键退出了,我们的程序也没有对按home键事件进行监听,在按home键时调用hideFragment,那么onHiddenChanged事实上没有被调用,反而是onPause被调用了。所以我们需要针对这样的情况做特殊的处理。比如在home键退出时显示调用一下hideFragment或者在onPause中也发信号说本Fragment不可见了,这都是可以的。

在ViewPager中的Fragment

现在安卓市场上基本上的app都会做tab页,而tab页基本都是通过android自带的ViewPager实现的。ViewPager有这样一个特点,当滑到某一个Tab时,它会同时加载这个tab的左右两个tab页,比如我从1页面切换到了2页面,那么3页面的onResume也被调用了,但是3页面其实对用户是不可见的。这时候我们就需要监听setUserVisibleHint来判断到底对用户是否可见。

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
//TODO now it's visible to user
} else {
//TODO now it's invisible to user
}
}

但是与第二条类似,我们依然不能完全依赖setUserVisibleHint这个方法来判断是否ViewPager中的页面是否对用户可见。因为该方法只有在Fragment切换的时候被调用。比如我从一个含有ViewPager的Actvity跳转到另一个activity,ViewPager中的Fragment的 setUserVisibleHint方法是不会被调用的,只能通过onPause来判断。进入该Activity原理类似。那么怎么办呢,我们需要结合setUserVisibleHint和onResume和onPause。

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if ((isVisibleToUser && isResumed())) {
onResume();
} else if (!isVisibleToUser) {
Timber.i("On Pause on %s Fragment Invisble", getClass().getSimpleName());
onPause()
}
}
@Override
public void onResume() {
super.onResume();
if (getUserVisibleHint()) {
Timber.i("On Resume on %s Fragment Visible", getClass().getSimpleName());
//TODO give the signal that the fragment is visible
}
} @Override
public void onPause() {
super.onPause();
//TODO give the signal that the fragment is invisible
}

需要注意以上方法并不完美,Fragment不可见的信号会被多次发送。目前还没找到一个只发送一次的方法。如果读者有更好的解决方案,欢迎跟我交流。

如何判断Fragment是否对用户可见的更多相关文章

  1. Ifvisible.js – 判断网页中的用户是闲置还是活动状态

    ifvisible.js 是一个跨浏览器.轻量级的方式,用户检查用户在浏览页面或正在与它进行交互.它可以处理活动状态,如在页面上空闲或活跃.您还可以使用 ifvisible.js 智能设置您的间隔,如 ...

  2. WinForm中如何判断关闭事件来源于用户点击右上角的“关闭”按钮

    在C#的WinForm程序中,有的时候需要判定关闭请求从哪里发出来的.比如是用户点击了右上角的“关闭”按钮,还是调用了WinForm.Close()方法.最典型的是要知道点击右上角的“关闭”按钮发出的 ...

  3. 从a站点跳转到b站点,通过url的参数判断是否让该用户选择身份

    一.问题的由来 问题是这样子给出来,今天产品那边跟我说,在a网站跳转到b网站时,让用户有一个选择身份的弹窗.因为公司有两个不同站点,你无论在a或者b网站注册后,都可以随便登录这两个站点,进入之后都会有 ...

  4. [Go] gocron源码阅读-判断是否使用root用户执行

    判断是linux系统,并且uid为0,allowRoot是通过命令行传参传进来的,通过flag包解析出来的,可以使用go run node.go -h看到这些参数 && !allowR ...

  5. 图解js中常用的判断浏览器窗体、用户屏幕可视区域大小位置的方法

    有时我们需要获得浏览器窗口或屏幕的大小.窗口下拉框下拉的距离等数据,对应这些需求,js中提供了不少解决方法,只是数量稍多容易混淆它们各自的意义,下面咱们用图例来解释下12个常见对象属性的作用. 其中有 ...

  6. PHP判断访问系统的用户设备类型

    当今的电子设备越来越多,我们在开发过程中往往也需要分析用户使用的电子设备类型.下面是采用PHP代码来获取用户使用的哪些类型的电子设备来访问自己的平台. /** * 用户设备类型 * @return s ...

  7. 多重条件判断SQL:用于用户名称,密码,权限的检测和判断

    string sqlstr = "select count(*) from tb_admin where 用户名='"+UserName+"'and 密码='" ...

  8. 对于Fragment的一些理解

    前言 Fragment想必大家不陌生吧,在日常开发中,对于Fragment的使用也很频繁,现在主流的APP中,基本的架构也都是一个主页,然后每个Tab项用Fragment做布局,不同选项做切换,使用起 ...

  9. Android开发 ---Fragment片段布局

    前言 Fragment想必大家不陌生吧,在日常开发中,对于Fragment的使用也很频繁,现在主流的APP中,基本的架构也都是一个主页,然后每个Tab项用Fragment做布局,不同选项做切换,使用起 ...

随机推荐

  1. EOF

    Process to end of file 就是处理到文件的结束 以经典的 A + B Problem 为例 把每一行的两个数字加起来,然后打印出来,直到文件末尾 c 语言表示:

  2. const变量与define定义常量的区别

    一.概念性区别 const 变量就是在普通变量前边加上一个关键字const,它赋值的唯一机会就是“定义时”,此变量不能被程序修改,存储在rodata区. define定义的是常量,不是变量,所以编译器 ...

  3. c# 中List<T> union 深入理解

    http://www.cnblogs.com/qinpengming/archive/2012/12/03/2800202.html 借用 这个兄弟的代码 我就不献丑了 .我这里指记录下 public ...

  4. Abstract Factory

    工厂模式比较好理解,其实就是通过访问工厂返回单一的对象/多个对象.那么抽象工厂就是返回多个抽象对象.这意味工厂返回对象纵向的一个扩展.但是很多时候,抽象工厂是两个维度的扩展,比方说在数据库类型和表对象 ...

  5. android小知识

    string 与 []byte 互转: public String BytesToString(byte[] data) { return new String(data); } public byt ...

  6. constant属性详解

    /**是否使用开发模式,不在开发模式下变为false*/ (常用) <constant name = "struts.devmode" value = "true& ...

  7. 你的 Docker 应用是安全的吗?

    近一年来,Docker 已经逐渐成为 container 界的事实标准,成为技术人员不可或缺的技能之一,就像 Docker 宣称的那样,「Build,Ship,and Run Any App,Anyw ...

  8. poj2954

    水题,先用叉积求三角形面积然后求三边上的点(由公约数上点)a然后用pick定理S=a+b/2-1就可以求出内部的点数了 var x,y,xx,yy,a1,a2,a3,x1,x2,x3,y1,y2,y3 ...

  9. 贪心(哈夫曼树):HDU 5884 sort

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA2QAAAKACAIAAAB8KCy/AAAgAElEQVR4nOy9a5Adx3UmWL+kHxuekU ...

  10. web.xml中的contextConfigLocation的作用

    在web.xml中通过contextConfigLocation配置spring,contextConfigLocation 参数定义了要装入的 Spring 配置文件. 如果想装入多个配置文件,可以 ...