【Android】友盟统计Fragment页面显示隐藏的完美解决方案

来源:互联网 发布:增值税税金计算器软件 编辑:程序博客网 时间:2024/06/03 12:53

【Android】友盟统计Fragment页面显示隐藏的完美解决方案

字数887 阅读3111 评论22 

在使用友盟统计的时候常常会遇到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

0 0
原创粉丝点击