在使用友盟统计的时候常常会遇到Activity加Fragment的组合,统计起来比较麻烦。
友盟给出的解决方案是在Activity的onResume()和onPause()方法中执行MobclickAgent.onResume()加MobclickAgent.onPause()统计时长然后在Fragment的onResume()和onPause()方法中执行MobclickAgent.onPageStart()加MobclickAgent.onPageEnd()统计页面
默认情况下在MobclickAgent.onResume()和MobclickAgent.onPause()方法中会自动执行MobclickAgent.onPageStart()和MobclickAgent.onPageEnd()来统计页面,要想不自动统计页面只需在Application或程序入口处执行MobclickAgent.openActivityDurationTrack(false)即可
这个方案在普通的使用方式中没啥问题,但在ViewPager中却有很严重的BUG。
众所周知ViewPager会在初始化的时候一次性初始化2个Fragment,并且这两个Fragment都处于resume状态。但用户只能看到第一个Fragment,这时候你能说第二个Fragment也显示了吗?我们只能说第二个Fragment也准备好了,不能说显示了。这样带来的BUG就是明明第二个Fragment用户都没有看到,却统计成了已显示。
那么还有没有合适的回调方法能够帮助我们准确的统计Fragment呢?当然有。
Fragment有个叫setUserVisibleHint(boolean)的方法就是专门设置显示不显示的,ViewPager会在初始化Fragment的时候以及切换Fragment的时候调用此方法设置是否显示。那是不是只重写这个方法然后调用MobclickAgent.onPageStart()加MobclickAgent.onPageEnd()就可以了,经过验证后只能很遗憾的告诉你,不可以!
因为ViewPager会在设置Adapter之后立即调用第一个、第二个fragment的setUserVisibleHint(boolean)方法设置为false,然后会对第一个fragment再次调用setUserVisibleHint(boolean)方法设置为true,然后才是onAttach()、onCreate(),很明显顺序不对。 另外当Fragment不是在ViewPager中使用的时候压根就不会调用setUserVisibleHint(boolean)方法
那么最终我们还是要结合Fragment的setUserVisibleHint(boolean)、onResume()、onPause()这三个方法才能完美的统计,最终实现方式如下所示:
public class MyFragment extends Fragment { private String pageName; public MyFragment() { pageName = getClass().getSimpleName(); } @Override public void onResume() { super.onResume(); if(getUserVisibleHint()){ onVisibilityChangedToUser(true, false); } } @Override public void onPause() { super.onPause(); if(getUserVisibleHint()){ onVisibilityChangedToUser(false, false); } } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if(isResumed()){ onVisibilityChangedToUser(isVisibleToUser, true); } } /** * 当Fragment对用户的可见性发生了改变的时候就会回调此方法 * @param isVisibleToUser true:用户能看见当前Fragment;false:用户看不见当前Fragment * @param isHappenedInSetUserVisibleHintMethod true:本次回调发生在setUserVisibleHintMethod方法里;false:发生在onResume或onPause方法里 */ public void onVisibilityChangedToUser(boolean isVisibleToUser, boolean isHappenedInSetUserVisibleHintMethod){ if(isVisibleToUser){ if(pageName != null){ MobclickAgent.onPageStart(pageName); Log.i("UmengPageTrack", pageName + " - display - "+(isHappenedInSetUserVisibleHintMethod?"setUserVisibleHint":"onResume")); } }else{ if(pageName != null){ MobclickAgent.onPageEnd(pageName); Log.w("UmengPageTrack", pageName + " - hidden - "+(isHappenedInSetUserVisibleHintMethod?"setUserVisibleHint":"onPause")); } } }}```重点就是在setUserVisibleHint(boolean)中加上isResume()过滤,在onResume()和onPause()中加上getUserVisibleHint()过滤有同学该担心了,你上面不是说在普通使用方式中setUserVisibleHint(boolean)压根就不会被调用,那么意味着getUserVisibleHint()一直都是false,最终onResume()和onPause()中的代码根本就不会执行了,这样普通使用方式就不行了啊。我要告诉大家的是大家的是Fragment的源码中明确显示,getUserVisibleHint()方法返回的是mUserVisibleHint字段的值,而mUserVisibleHint字段默认值是true如果你需要ViewPager嵌套ViewPager,那么你还会遇到Fragment的mUserVisibleHint属性不同步的问题,请查看下一篇文章来解决下一篇:[【Android】解决ViewPager嵌套时Fragment的mUserVisibleHint属性不同步的问题](http://www.jianshu.com/p/e7449278e33d)复制代码