最近在开发中遇到了一个问题。咱们的app须要统计用户的页面路径,也就是用户使用各个页面的状况。这就须要在不一样的页面跳入和跳出时记录下来。可是咱们的app主要是由Fragment构成的。而在不一样的使用状况下,判断Fragment是否可见的方法是不同的。下面对这些不一样的使用状况分开分析。android
这种状况是最简单的,也就是在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 }
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
如今安卓市场上基本上的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不可见的信号会被屡次发送。目前还没找到一个只发送一次的方法。若是读者有更好的解决方案,欢迎跟我交流。开发