Fragment 可见性监听通过androidx 运行,多种 case 完美兼容!

本文介绍了如何在AndroidX环境下监听Fragment的可见性,包括Replace、Hide/Show、ViewPager嵌套Fragment及宿主Fragment再嵌套Fragment等场景。通过onResume/onPause、onHiddenChanged、setUserVisibleHint方法,结合源码分析和实践案例,提供完整解决方案。
摘要由CSDN通过智能技术生成

前言

本篇文章主要提供一种监听 Fragment 可见性监听的方案,完美适配多种 case,有兴趣的可以看看。废话不多说,开始进入正文。

在开发当中, fragment 经常使用到。在很多应用场景中,我们需要监听到fragment 的显示与隐藏,来进行一些操作。比如,统计页面的停留时长,页面隐藏的时候停止播放视频。

有些同学可能会说了,这还不容易,直接监听 Fragment 的onResume,onPause。我只能说,兄弟,too young,too simple。

下面,让我们一起来实现 fragment 的监听。主要分为几种 case:

1、一个页面只有一个 fragment 的,使用 replace。

2、Hide 和 Show 操作。

3、ViewPager 嵌套 Fragment。

4、宿主 Fragment 再嵌套 Fragment,比如 ViewPager 嵌套ViewPager,再嵌套 Fragment。

1.Replace 操作

replace 操作这种比较简单,因为他会正常调用 onResume 和 onPause 方法,我们只需要在 onResume 和 onPause 做 check 操作即可。

override fun onResume() {
   
    info("onResume")
    super.onResume()
    onActivityVisibilityChanged(true)
}


override fun onPause() {
   
    info("onPause")
    super.onPause()
    onActivityVisibilityChanged(false)
}

2.Hide 和 Show 操作

Hide 和 show 操作,会促发生命周期的回调,但是 hide 和 show 操作并不会,那么我们可以通过什么方法来监听呢?其实很简单,可以通过onHiddenChanged 方法。

/**
 * 调用 fragment show hide 的时候回调用这个方法
 */
override fun onHiddenChanged(hidden: Boolean) {
   
    super.onHiddenChanged(hidden)
    checkVisibility(hidden)
}

3.ViewPager 嵌套 Fragmen

ViewPager 嵌套 Fragment,这种也是很常见的一种结构。因为 ViewPager的预加载机制,在 onResume监听是不准确的。

这时候,我们可以通过 setUserVisibleHint 方法来监听,当方法传入值为true的时候,说明Fragment可见,为false的时候说明Fragment被切走了。

public void setUserVisibleHint(boolean isVisibleToUser)

有一点需要注意的是,个方法可能先于Fragment的生命周期被调用(在FragmentPagerAdapter中,在Fragment被add之前这个方法就被调用了),所以在这个方法中进行操作之前,可能需要先判断一下生命周期是否执行了。

/**
 * Tab切换时会回调此方法。对于没有Tab的页面,[Fragment.getUserVisibleHint]默认为true。
 */
@Suppress("DEPRECATION")
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
   
    info("setUserVisibleHint = $isVisibleToUser")
    super.setUserVisibleHint(isVisibleToUser)
    checkVisibility(isVisibleToUser)
}

/**
 * 检查可见性是否变化
 *
 * @param expected 可见性期望的值。只有当前值和expected不同,才需要做判断
 */
private fun checkVisibility(expected: Boolean) {
   
    if (expected == visible) return
    val parentVisible = if (localParentFragment == null) {
   
        parentActivityVisible
    } else {
   
        localParentFragment?.isFragmentVisible() ?: false
    }
    val superVisible = super.isVisible()
    val hintVisible = userVisibleHint
    val visible = parentVisible && superVisible && hintVisible
    info(
            String.format(
                    "==> checkVisibility = %s  ( parent = %s, super = %s, hint = %s )",
                    visible, parentVisible, superVisible, hintVisible
            )
    )
    if (visible != this.visible) {
   
        this.visible = visible
        onVisibilityChanged(this.visible)
    }
}

AndroidX 的适配(也是一个坑)

在 AndroidX 当中,FragmentAdapter 和FragmentStatePagerAdapter 的构造方法,添加一个 behavior 参数实现的。

如果我们指定不同的 behavior,会有不同的表现。

1、当 behavior 为BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 时,ViewPager中切换 Fragment,setUserVisibleHint 方法将不再被调用,他会确保onResume 的正确调用时机。

2、当 behavior 为 BEHAVIOR_SET_USER_VISIBLE_HINT,跟之前的方式是一致的,我们可以通过 setUserVisibleHint 结合 fragment 的生命周期来监听。


//FragmentStatePagerAdapter构造方法
public FragmentStatePagerAdapter(@NonNull FragmentManager fm,
        @Behavior int behavior) {
   
    mFragmentManager = fm;
    mBehavior = behavior;
}

//FragmentPagerAdapter构造方法
public FragmentPagerAdapter(@NonNull FragmentManager fm,
        @Behavior int behavior) {
   
    mFragmentManager =
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值