博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
判断Fragment是否对用户可见
阅读量:6271 次
发布时间:2019-06-22

本文共 8096 字,大约阅读时间需要 26 分钟。

转载请标明出处: ,谢谢。

背景

最近在开发过程中遇到了若干问题,比如

  1. 页面统计
  2. Banner轮播的启动与暂停
  3. 等等其他自定义需求

在Activity中这些可以很简单的达到目的,但是如果页面中有Fragment,那就无法像Activity那样简单的实现,下面针对Fragment不同的使用方法进行分析。

各种使用方法

1. 在Activity中直接使用

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

@Overridepublic void onResume() {    super.onResume();    // TODO now it's visible to user}@Overridepublic void onPause() {    super.onPause();    // TODO now it's invisible to user}复制代码

2. 使用show和hide来显隐的Fragment

FragmentManager除了addFragment和replaceFragment之外还有showFragment和hideFragment来做Fragment的显隐,这样可以提生页面切换的速度,是一种用空间换时间的方式。但是这样使用的Fragment在被hide的时候是不会调用onPause方法的。因为它只是在屏幕中不可见了,但是没有Pause。这时候我们需要监听onHiddenChanged方法。

@Overridepublic void onHiddenChanged(boolean hidden) {    super.onHiddenChanged(hidden);	if (!hidden) {		// TODO now it's visible to user	} else {		// TODO now it's invisible to user	}}复制代码

3. 在ViewPager中的Fragment

现在很多app都会做tab页,而tab页基本都是通过android自带的ViewPager实现的。ViewPager有这样一个特点,当滑到某一个Tab时,它会同时加载这个tab的左右两个tab页,比如我从1页面切换到了2页面,那么3页面的onResume也被调用了,但是3页面其实对用户是不可见的。这时候我们就需要监听setUserVisibleHint来判断到底对用户是否可见。

@Overridepublic void setUserVisibleHint(boolean isVisibleToUser) {    super.setUserVisibleHint(isVisibleToUser);	if (isVisibleToUser) {		// TODO now it's visible to user	} else {		// TODO now it's invisible to user	}}复制代码

注意!!!注意!!!注意!!!

在以下几种操作情况下:

  1. startActivity页面跳转
  2. 按Home键返回主屏
  3. 从其他页面或主屏返回
  4. 等等和上面类似的操作

只要用户进行了以上操作,那么上述列出的所有使用方法中,只要是处于同一个Activity中的Fragment,那么不管是否显示,都会且只会调用onResume或onPause方法。

比如:

在一个Activity中分别有Fragment A、B,其中在Fragment A中内嵌了Fragment a、b。

  1. 当返回主屏或者跳转新页面时,Fragment A、B、a、b四个均会执行onPause方法,而onHiddenChanged和setUserVisibleHint两个方法不会被执行。
  2. 同样,当返回Activity页面时,Fragment A、B、a、b四个均会执行onResume方法,而onHiddenChanged和setUserVisibleHint两个方法不会被执行。

正是因为上述问题的存在,所以需要onHiddenChanged、setUserVisibleHint、onResume、onPause四个方法相互结合一起来判断。

代码如下

public abstract class BaseFrameFragment extends Fragment {    public BaseFrameActivity activity;    private boolean isFirstCreate;// 是否是第一次创建    private boolean isVisibleToUser;// 当前可见状态    private boolean isLastVisibleToUser;// 最后一次可见状态(onPause前的最后一次状态)    @Override    public void onAttach(Context context) {        super.onAttach(context);        LogUtil.i("onAttach:" + getFragmentName());        FragmentActivity activity = getActivity();        if (activity instanceof BaseFrameActivity) {            this.activity = (BaseFrameActivity) activity;        } else {            throw new IllegalArgumentException("Activity 必须继承 BaseFrameActivity");        }    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        LogUtil.i("onCreateView:" + getFragmentName());        View layout_root = View.inflate(activity, getContentViewResourceId(), null);        initData(getArguments());        initView(layout_root);        loadData();        setListener();        isFirstCreate = true;        return layout_root;    }    /**     * 使用showFragment和hideFragment来做Fragment的显隐时判断Fragment是否可见     *     * @param hidden 是否隐藏     */    @Override    public void onHiddenChanged(boolean hidden) {        super.onHiddenChanged(hidden);        LogUtil.i("onHiddenChanged:" + getFragmentName() + " " + hidden);        isLastVisibleToUser = !hidden;        onVisibleToUser(isLastVisibleToUser);        setChildVisibleToUser(isLastVisibleToUser);    }    /**     * 使用ViewPager来做Fragment的显隐时判断Fragment是否可见     *     * @param isVisibleToUser 是否可见     */    @Override    public void setUserVisibleHint(boolean isVisibleToUser) {        super.setUserVisibleHint(isVisibleToUser);        if (activity == null) {            LogUtil.i("setUserVisibleHint:" + isVisibleToUser);            return;        }        LogUtil.i("setUserVisibleHint:" + getFragmentName() + " " + isVisibleToUser);        isLastVisibleToUser = isVisibleToUser;        onVisibleToUser(isLastVisibleToUser);        setChildVisibleToUser(isLastVisibleToUser);    }    /**     * 在Activity使用XML引入,或者使用FragmentManager 的addFragment或者replaceFragment 动态载入时判断Fragment是否可见     * startActivity切换页面或者Home键切入后台后回到原页面也会调用此方法     */    @Override    public void onResume() {        super.onResume();        LogUtil.i("onResume:" + getFragmentName());        // 第一次创建且显示给用户(ViewPager) 或 回到原页面前可见状态且ParentFragment isLastVisibleToUser状态        if ((isFirstCreate && getUserVisibleHint()) || (isLastVisibleToUser && getParentFragmentLastVisibleToUser())) {            onVisibleToUser(true);        }    }    /**     * 在Activity使用XML引入,或者使用FragmentManager 的addFragment或者replaceFragment 动态载入时判断Fragment是否可见     * startActivity切换页面或者Home键切入后台也会调用此方法     */    @Override    public void onPause() {        super.onPause();        LogUtil.i("onPause:" + getFragmentName());        if (isLastVisibleToUser) {            onVisibleToUser(false);        }    }    /**     * 获取ParentFragment isLastVisibleToUser状态(没有则为true)     *     * @return ParentFragment isLastVisibleToUser     */    private boolean getParentFragmentLastVisibleToUser() {        Fragment parentFragment = getParentFragment();        if (parentFragment != null) {            if (parentFragment instanceof BaseFrameFragment) {                BaseFrameFragment frameFragment = (BaseFrameFragment) parentFragment;                return frameFragment.isLastVisibleToUser;            }        }        return true;    }    /**     * 设置子Fragment显示状态     *     * @param isVisibleToUser isVisibleToUser     */    private void setChildVisibleToUser(boolean isVisibleToUser) {        List
fragmentList = getChildFragmentManager().getFragments(); if (!BaseUtils.isEmptyList(fragmentList)) { for (Fragment fragment : fragmentList) { if (fragment instanceof BaseFrameFragment) { BaseFrameFragment frameFragment = (BaseFrameFragment) fragment; if (frameFragment.isLastVisibleToUser) { frameFragment.onVisibleToUser(isVisibleToUser); } } } } } public abstract String getFragmentName(); /** * 获取根布局ResourceId * * @return 根布局ResourceId */ public abstract int getContentViewResourceId(); /** * 初始化数据,主要包括拆包从activity传递过来的参数,适配器初始化,集合初始化等,不可进行view的操作 * * @param arguments 接收到的从其他地方传递过来的参数 */ public abstract void initData(Bundle arguments); /** * 初始化View * * @param layout_root Fragment View */ public abstract void initView(View layout_root); /** * 加载数据,在onCreateView方法中调用可以直接理解为加载数据,方法中可以进行view的操作 */ public abstract void loadData(); /** * 设置监听 */ public abstract void setListener(); /** * 对用户可见/不可见时执行的操作(类似Activity的onResume/onPause方法) * * @param isVisibleToUser 是否对用户显示可见 */ public void onVisibleToUser(boolean isVisibleToUser) { if (this.isVisibleToUser == isVisibleToUser) { return; } LogUtil.i("onVisibleToUser:" + getFragmentName() + " " + isVisibleToUser); this.isVisibleToUser = isVisibleToUser; isFirstCreate = false; if (isVisibleToUser) { isLastVisibleToUser = true; } }}复制代码

具体使用

public class A_TempFragment extends BaseFrameFragment {    @Override    public String getFragmentName() {        return getString(R.string.app_name);    }    @Override    public int getContentViewResourceId() {        return R.layout.activity_base;    }    @Override    public void initData(Bundle arguments) {    }    @Override    public void initView(View layout_root) {        ButterKnife.bind(this, layout_root);    }    @Override    public void loadData() {    }    @Override    public void setListener() {    }    @Override    public void onVisibleToUser(boolean isVisibleToUser) {        super.onVisibleToUser(isVisibleToUser);        if (isVisibleToUser) {            // TODO now it's visible to user        } else {            // TODO now it's invisible to user        }    }    }复制代码

目前在Activity嵌入Fragment,Fragment内嵌ViewPager+Fragment使用中,一切正常 欢迎一起讨论

参考资料

转载于:https://juejin.im/post/5a30c5016fb9a0450a6755b2

你可能感兴趣的文章
(转)使用C#开发ActiveX控件
查看>>
spring mvc 基于注解 配置默认 handlermapping
查看>>
半小时学会上传本地项目到github
查看>>
Android学Jni/Ndk 开发记录(一)
查看>>
Linux Tcl和Expect的安装
查看>>
WPF中的依赖项属性(转)
查看>>
linux防火墙相关 iptables
查看>>
最简单的单例模式
查看>>
JPopupMenu的使用以及JPopupMenu中子组件的事件处理
查看>>
从反汇编的角度看引用和指针的区别
查看>>
拓马长枪定乾坤
查看>>
UIProgressView的详细使用
查看>>
Silverlight实用窍门系列:70.Silverlight的视觉状态组VisualStateGroup
查看>>
照片筛选与上传功能
查看>>
Hello ZED
查看>>
常见web攻击方式
查看>>
hdu 4472
查看>>
oracle存储过程中is和as区别
查看>>
windows 2003 群集
查看>>
几个gcc的扩展功能
查看>>