1. 自测 场景

简易场景 {      // 只考虑最后一个 Fragmentcase1:  Activity + Fragment case2:  Activity + FragmentA + FragmentB 「只考虑 FragmentB 自身的变化」case3:  Activity + ViewPager + Fragment case4:  Activity + ViewPager2 + Fragment
}复杂场景 {  case1:  Activity + FragmentA + FragmentB// FragmentA 可见性 变化,对 FragmentB 的影响
}

2. 自测 场景结果

2.1.1 简易场景 case1

case1:  Activity + Fragment {replace = remove + addadd(int, fragment)          onCreate() -> onActivityCreated() -> onResume()remove(fragment)            onPause() -> onDestroy()hide(fragment)              onHiddenChanged(true)show(fragment)              onHiddenChanged(false)息屏(fragmentA)              onPause()亮屏(fragmentA)              onResume()
}

2.1.2 简易场景 case2

case2:  Activity + FragmentA + FragmentB 「只考虑 FragmentB 自身的变化」{replace = remove + addadd(int, fragment)          onCreate() -> onActivityCreated() -> onResume()remove(fragment)            onPause() -> onDestroy()hide(fragment)              onHiddenChanged(true)show(fragment)              onHiddenChanged(false)息屏(fragmentA)              onPause()亮屏(fragmentA)              onResume()
}

2.1.3 简易场景 case3

case3:  Activity + ViewPager + Fragment {viewpager.count = 7viewpager.offscreenPageLimit = 1{初始化 index = 0 { text0text0:  onCreate() -> onActivityCreated() -> onResume()text1:  onCreate() -> onActivityCreated() -> onResume()}右滑 第 1 次 { text1text0:  setUserVisibleHint(false)text1:  setUserVisibleHint(true)text2:  onCreate() -> onActivityCreated() -> onResume()}息屏 {    text1text0:  onPause()text1:  onPause()text2:  onPause()}亮屏 {    text1text0:  onResume()text1:  onResume()text2:  onResume()}右滑 第 2 次 { text2text0:  onPause()text1:  setUserVisibleHint(false)text2:  setUserVisibleHint(true)text3:  onCreate() -> onActivityCreated() -> onResume()}}viewpager.count = 7viewpager.offscreenPageLimit = 2{初始化 index = 0 { text0text0:  onCreate() -> onActivityCreated() -> onResume()text1:  onCreate() -> onActivityCreated() -> onResume()text2:  onCreate() -> onActivityCreated() -> onResume()}右滑 第 1 次 { text1text0:  setUserVisibleHint(false)text1:  setUserVisibleHint(true)text3:  onCreate() -> onActivityCreated() -> onResume()}右滑 第 2 次 { text2text1:  setUserVisibleHint(false)text2:  setUserVisibleHint(true)text4:  onCreate() -> onActivityCreated() -> onResume()}}
}

2.1.4 简易场景 case4

case4:  Activity + ViewPager2 + Fragment {viewpager2.count = 7viewpager2.offscreenPageLimit = 1{初始化 index = 0 { text0text0:  onCreate() -> onActivityCreated() -> onResume()text1:  onCreate() -> onActivityCreated()}右滑 第 1 次 { text1text0:  onPause()text1:  onResume()text2:  onCreate() -> onActivityCreated()}息屏 {    text1text1:  onPause()}亮屏 {    text1text1:  onResume()}右滑 第 2 次 { text2text1:  onPause()text2:  onResume()text3:  onCreate() -> onActivityCreated()}左滑 第 1 次 { text1text2:  onPause()text1:  onResume()}}viewpager2.count = 7viewpager2.offscreenPageLimit = 2{初始化 index = 0 { text0text0:  onCreate() -> onActivityCreated() -> onResume()text1:  onCreate() -> onActivityCreated()text2:  onCreate() -> onActivityCreated()}右滑 第 1 次 { text1text0:  onPause()text1:  onResume()text3:  onCreate() -> onActivityCreated()}右滑 第 2 次 { text2text1:  onPause()text2:  onResume()text4:  onCreate() -> onActivityCreated()}左滑 第 1 次 { text1text1:  onResume()text2:  onPause()}}
}

2.2.1 复杂场景 case1

考虑到场景复杂,父容器 和 子容器,只做1个通知即可。代码如下:

/*** 作为父Fragment, visible 变化后,通知child*/
fun dispatch2Child(fragment: Fragment, visible: Boolean) {val childFragments = fragment.childFragmentManager.fragments// 没有 childif (childFragments.isEmpty()) {return}// 当前Fragment可见性修改,通知下去childFragments.forEachIndexed { index, child ->if (child.isAdded && child is OnVisibleListener) {child.onParentFragmentVisibleChanged(visible)}}
}class ChildFragment: Fragment(), OnVisibleListener {override fun onParentFragmentVisibleChanged(parentVisible: Boolean) {// TODO 给一个默认 逻辑;可被复写}
}

3. 代码实现

1. BaseFragment    // 基类

2. VisibleJobImpl   // 对接 BaseFragment,和 具体功能的实现类

3. VisibleLogJob  // 提供 BaseFragment 生命周期的日志功能

4. VFunctionVP2Job、VFunctionLayoutJob、VFunctionVPJob   // 适配 ViewPager、ViewPager2 等场景


abstract class BaseFragment : Fragment(), OnVisibleListener {var logTag: String? = ""private var visibleJob = VisibleJobImpl()protected abstract fun getLayoutId(): Intoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)visibleJob.setLogTag(logTag)visibleJob.setOnVisibleListener(this)visibleJob.onCreate(this)}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)val customJob = onCreateFunctionJob()if (null != customJob) {visibleJob.setFunctionJob(customJob)} else {// 自动查找 场景val functionJob = when (VisibleJobImpl.findParentContainerCase(view.parent, 3)) {VisibleJobImpl.CASE_CONTAINER_LAYOUT -> VFunctionLayoutJob()VisibleJobImpl.CASE_CONTAINER_VIEWPAGER -> VFunctionVPJob()VisibleJobImpl.CASE_CONTAINER_VIEWPAGER2 -> VFunctionVP2Job()else -> null}visibleJob.setFunctionJob(functionJob)}}override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {return inflater.inflate(getLayoutId(), container, false)}override fun onActivityCreated(savedInstanceState: Bundle?) {super.onActivityCreated(savedInstanceState)visibleJob.onActivityCreated()}override fun onResume() {super.onResume()visibleJob.onResume()}override fun onPause() {visibleJob.onPause()super.onPause()}override fun onDestroy() {visibleJob.onDestroy()super.onDestroy()}override fun setUserVisibleHint(isVisibleToUser: Boolean) {super.setUserVisibleHint(isVisibleToUser)visibleJob.setUserVisibleHint(isVisibleToUser)}override fun onHiddenChanged(hidden: Boolean) {super.onHiddenChanged(hidden)visibleJob.onHiddenChanged(hidden)}open fun onCreateFunctionJob(): OnVisibleLifecycleJob? {return null}fun getVisibleJobImpl(): VisibleJobImpl {return visibleJob}private var nextShouldVisible = false   // 父容器改变时,下一次是否需要修改可变性override fun onParentFragmentVisibleChanged(parentVisible: Boolean) {visibleJob.print("onParentFragmentVisibleChanged($parentVisible)")if (parentVisible) {    // 父容器,不可见 -> 可见if (nextShouldVisible) {visibleJob.updateVisible(true)}} else {    // 父容器,可见 -> 不可见if (isVisible) {visibleJob.updateVisible(false)nextShouldVisible = true}}}open override fun onFragmentFirstVisible() {}open override fun onFragmentVisible() {}open override fun onFragmentInvisible() {}
}
class VisibleJobImpl {private var logJob: VisibleLogJob? = null   // 日志实现private var functionJob: OnVisibleLifecycleJob? = null  // 功能实现private var hostFragment: Fragment? = null   // 宿主Fragmentprivate var visibleListener: OnVisibleListener? = nullfun setOnVisibleListener(listener: OnVisibleListener) {this.visibleListener = listener}fun setFunctionJob(functionJob: OnVisibleLifecycleJob?) {print("setFunctionJob: ${functionJob?.javaClass?.simpleName}")this.functionJob = functionJob}fun onCreate(fragment: Fragment) {this.hostFragment = fragmentlogJob = VisibleLogJob()logJob?.onCreate(fragment, this)functionJob?.onCreate(fragment, this)}fun onActivityCreated() {logJob?.onActivityCreated(this)functionJob?.onActivityCreated(this)}fun onResume() {logJob?.onResume(this)functionJob?.onResume(this)}fun onPause() {logJob?.onPause(this)functionJob?.onPause(this)}fun onDestroy() {logJob?.onDestroy(this)functionJob?.onPause(this)this.hostFragment = null    // 清空}fun setUserVisibleHint(isVisibleToUser: Boolean) {logJob?.setUserVisibleHint(this, isVisibleToUser)functionJob?.setUserVisibleHint(this, isVisibleToUser)}fun onHiddenChanged(hidden: Boolean) {logJob?.onHiddenChanged(this, hidden)functionJob?.onHiddenChanged(this, hidden)}private var logHeader = ""private var hasFirstVisible = falseprivate var nowVisible = false/*** className: ==FragmentA*/fun setLogTag(className: String? = "") {this.logHeader = "xxq==$className"  // 案例: "xxq====FragmentA"}/*** 修改可见性*/fun updateVisible(visible: Boolean) {val fragment = hostFragment ?: returnif (nowVisible == visible) {return}nowVisible = visible// 当前Fragment 可见性修改if (visible) {callVisible()} else {callInvisible()}// 可见性 变化后,分发给 childdispatch2Child(fragment, visible)}/*** 可见*/private fun callVisible() {if (!hasFirstVisible) {hasFirstVisible = truevisibleListener?.onFragmentFirstVisible()print("onFragmentFirstVisible")}visibleListener?.onFragmentVisible()print("onFragmentVisible")}/*** 不可见*/private fun callInvisible() {visibleListener?.onFragmentInvisible()print("onFragmentInvisible")}/*** 打印日志,adb shell setprop log.tag.xxq V*/fun print(method: String?) {if (Log.isLoggable("xxq", Log.DEBUG)) {Log.d("xxq", "$logHeader.$method")}}companion object {const val CASE_CONTAINER_KEY = "case_container_key"const val CASE_CONTAINER_LAYOUT = 0 // layout 加载 Fragmentconst val CASE_CONTAINER_VIEWPAGER = 1  // viewpager 加载 Fragmentconst val CASE_CONTAINER_VIEWPAGER2 = 2 // viewpager2 加载 Fragment/*** 作为父Fragment, visible 变化后,通知child*/fun dispatch2Child(fragment: Fragment, visible: Boolean) {val childFragments = fragment.childFragmentManager.fragments// 没有 childif (childFragments.isEmpty()) {return}// 当前Fragment可见性修改,通知下去childFragments.forEachIndexed { index, child ->if (child.isAdded && child is OnVisibleListener) {child.onParentFragmentVisibleChanged(visible)}}}/*** 向上查找容器,最多 level 层*/fun findParentContainerCase(view: ViewParent?, level: Int = 3): Int {if (null == view) {     // ViewPager2 时,viewParent 为空return CASE_CONTAINER_VIEWPAGER2}if (level <= 0) {   // 寻找几层,没有,默认 Layoutreturn CASE_CONTAINER_LAYOUT}if (view is ViewPager) {    // ViewPager 校验return CASE_CONTAINER_VIEWPAGER}// 递归查找return findParentContainerCase(view.parent, level - 1)}}
}
class VisibleLogJob : OnVisibleLifecycleJob {override fun onCreate(fragment: Fragment, jobImpl: VisibleJobImpl) {jobImpl.print("onCreate")}override fun onActivityCreated(jobImpl: VisibleJobImpl) {jobImpl.print("onActivityCreated")}override fun onResume(jobImpl: VisibleJobImpl) {jobImpl.print("onResume")}override fun onPause(jobImpl: VisibleJobImpl) {jobImpl.print("onPause")}override fun onDestroy(jobImpl: VisibleJobImpl) {jobImpl.print("onDestroy")}override fun setUserVisibleHint(jobImpl: VisibleJobImpl, isVisibleToUser: Boolean) {jobImpl.print("setUserVisibleHint($isVisibleToUser)")}override fun onHiddenChanged(jobImpl: VisibleJobImpl, hidden: Boolean) {jobImpl.print("onHiddenChanged($hidden)")}
}
class VFunctionVPJob : VFunctionLayoutJob() {private var hostFragment: Fragment? = nulloverride fun onCreate(fragment: Fragment, jobImpl: VisibleJobImpl) {this.hostFragment = fragment}override fun onActivityCreated(jobImpl: VisibleJobImpl) {}override fun onResume(jobImpl: VisibleJobImpl) {if (hostFragment?.userVisibleHint == true) {jobImpl.updateVisible(true)}}override fun onPause(jobImpl: VisibleJobImpl) {if (hostFragment?.userVisibleHint == true) {jobImpl.updateVisible(false)}}override fun onDestroy(jobImpl: VisibleJobImpl) {this.hostFragment = null}override fun setUserVisibleHint(jobImpl: VisibleJobImpl, isVisibleToUser: Boolean) {jobImpl.updateVisible(isVisibleToUser)}override fun onHiddenChanged(jobImpl: VisibleJobImpl, hidden: Boolean) {jobImpl.updateVisible(!hidden)}
}
class VFunctionVP2Job : VFunctionLayoutJob() {override fun onCreate(fragment: Fragment, jobImpl: VisibleJobImpl) {}override fun onActivityCreated(jobImpl: VisibleJobImpl) {}override fun onResume(jobImpl: VisibleJobImpl) {jobImpl.updateVisible(true)}override fun onPause(jobImpl: VisibleJobImpl) {jobImpl.updateVisible(false)}override fun onDestroy(jobImpl: VisibleJobImpl) {}override fun setUserVisibleHint(jobImpl: VisibleJobImpl, isVisibleToUser: Boolean) {}override fun onHiddenChanged(jobImpl: VisibleJobImpl, hidden: Boolean) {jobImpl.updateVisible(!hidden)}
}
open class VFunctionLayoutJob : OnVisibleLifecycleJob {override fun onCreate(fragment: Fragment, jobImpl: VisibleJobImpl) {}override fun onActivityCreated(jobImpl: VisibleJobImpl) {}override fun onResume(jobImpl: VisibleJobImpl) {jobImpl.updateVisible(true)}override fun onPause(jobImpl: VisibleJobImpl) {jobImpl.updateVisible(false)}override fun onDestroy(jobImpl: VisibleJobImpl) {}override fun setUserVisibleHint(jobImpl: VisibleJobImpl, isVisibleToUser: Boolean) {}override fun onHiddenChanged(jobImpl: VisibleJobImpl, hidden: Boolean) {jobImpl.updateVisible(!hidden)}
}

最新文章

  1. Java基础-集合:set
  2. 【使用Java编写的B*算法】
  3. Android系统服务
  4. IHttpHandler 介绍演示(from 张子阳)
  5. 搜索引擎原理和简单过程【转】
  6. Exchange与ADFS单点登录 PART 5:添加ADFS信赖方信任
  7. 数据结构之图:加权有向图与dijkstra算法找到最短路径,Python——28
  8. ubuntu14.04中安装opencv2.4.11
  9. 电脑今天关机,第二天重启 解决方案
  10. 经典游戏制作教程[zz]
  11. 伺服电机常用参数设置_伺服驱动器常见参数的设置
  12. Flash CS3无法导出测试影片问题解决
  13. OPICS 节假日维护
  14. 【word毕业论文排版(3)】word导出带有书签的PDF失败,转为用WPS成功
  15. 最小二乘法以及正交最小二乘(OLS)的推导与简单比较
  16. python控制步进电机代码tx2_步进电机按键控制.lst
  17. 用机器学习做风控的氪信,凭什么获金牌投资人章苏阳数千万融资?
  18. 史上最全的信息收集总结!!!
  19. Android 监听键盘事件
  20. cobbler sync 错误

热门文章

  1. Ubuntu20.04 在anaconda上,opencv-python支持h264编码
  2. 微信小程序 启动页自动跳转
  3. idea快速创建serilizableuid
  4. 传统媒体如何借力微信
  5. SecureCRT 经典配色方案
  6. 【渝粤题库】陕西师范大学202131组织行为学作业(高起本、专升本)
  7. 圆锥曲线的定值定点问题
  8. LaTeX Beamer 制作PPT时给某一页添加背景图片(并设置透明度)
  9. 给定一个英文字符串,请写一段代码找出这个字符串中首先出现三次的那个英文字符(需要区分大小写)。
  10. Python--绘制点