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


    背景

    最近在开发中遇到了一个问题。我们的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不可见的信号会被多次发送。目前还没找到一个只发送一次的方法。如果读者有更好的解决方案,欢迎跟我交流。

  • 相关阅读:
    简单理解ThreadLocal原理和适用场景
    Portal实现原理
    Spring cloud微服务实战——基于OAUTH2.0统一认证授权的微服务基础架构
    Java8中 Date和LocalDateTime的相互转换
    sonar rule
    图论篇2——最小生成树算法(kurskal算法&prim算法)
    图论篇1——图的基本概念
    数论篇6——欧拉函数
    数论篇5——数论四大定理
    数论篇4——逆元(数论倒数)
  • 原文地址:https://www.cnblogs.com/dongweiq/p/5411899.html
Copyright © 2020-2023  润新知