如何判断Fragment是否对用户可见

背景

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

不一样的状况

在Activity中直接使用

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

@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方法ide

@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不可见了,这都是能够的。spa

在ViewPager中的Fragment

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

@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不可见的信号会被屡次发送。目前还没找到一个只发送一次的方法。若是读者有更好的解决方案,欢迎跟我交流。开发

相关文章
相关标签/搜索