
前言
年后最后一篇文章啦,在这里先祝大家新年快乐~最重要的抽中
全家福
,明年继续修福报🤣
以前处理 Fragment 的懒加载,我们通常会在 Fragment 中处理 setUserVisibleHint + onHiddenChanged
这两个函数,而在 Androidx 模式下,我们可以使用 FragmentTransaction.setMaxLifecycle()
的方式来处理 Fragment 的懒加载。
在本文章中,我会详细介绍不同使用场景下两种方案的差异。大家快拿好小板凳。一起来学习新知识吧!
本篇文章涉及到的 Demo,已上传至Github---->传送门
老的懒加载处理方案
如果你熟悉老一套的 Fragment 懒加载机制,你可以直接查看 Androix 懒加载相关章节
add+show+hide 模式下的老方案
在没有添加懒加载之前,只要使用 add+show+hide
的方式控制并显示 Fragment, 那么不管 Fragment 是否嵌套,在初始化后,如果只调用了add+show
,同级下的 Fragment 的相关生命周期函数都会被调用。且调用的生命周期函数如下所示:
onAttach -> onCreate -> onCreatedView -> onActivityCreated -> onStart -> onResume
Fragment 完整生命周期:onAttach -> onCreate -> onCreatedView -> onActivityCreated -> onStart -> onResume -> onPause -> onStop -> onDestroyView -> onDestroy -> onDetach
什么是同级 Frament 呢?看下图

上图中,都是使用
add+show+hide
的方式控制 Fragment,
在上图两种模式中:
- Fragment_1、Fragment_2、Fragment_3 属于同级 Fragment
- Fragment_a、Fragment_b、Fragment_c 属于同级 Fragment
- Fragment_d、Fragment_e、Fragment_f 属于同级 Fragment
那这种方式会带来什么问题呢?结合下图我们来分别分析。

观察上图我们可以发现,同级的Fragment_1、Fragment_2、Fragment_3 都调用了 onAttach...onResume
系列方法,也就是说,如果我们没有对 Fragment 进行懒加载处理,那么我们就会无缘无故的加载一些并不可见
的 Fragment , 也就会造成用户流量的无故消耗(我们会在 Fragment 相关生命周期函数中,请求网络或其他数据操作)。
这里
"不可见的Fragment"
是指,实际不可见但是相关可见生命周期函数(如onResume
方法)被调用的 Fragment
如果使用嵌套 Fragment ,这种浪费流量的行为就更明显了。以本节的图一为例,当 Fragment_1 加载时,如果你在 Fragment_1 生命周期函数中使用 show+add+hide
的方式添加 Fragment_a、Fragment_b、Fragment_c
, 那么 Fragment_b 又会在其生命周期函数中继续加载 Fragment_d、Fragment_e、Fragment_f
。
那如何解决这种问题呢?我们继续接着上面的例子走,当我们 show Fragment_2
,并 hide其他 Fragment 时,对应 Fragment 的生命周期调用如下:

从上图中,我们可以看出 Fragment_2 与 Fragment_3 都调用了 onHiddenChanged
函数,该函数的官方 API 声明如下:
/**
* Called when the hidden state (as returned by {@link #isHidden()} of
* the fragment has changed. Fragments start out not hidden; this will
* be called whenever the fragment changes state from that.
* @param hidden True if the fragment is now hidden, false otherwise.
*/
public void onHiddenChanged(boolean hidden) {
}
根据官方 API 的注释,我们大概能知道,当 Fragment 隐藏的状态发生改变时,该函数将会被调用,如果当前 Fragment 隐藏, hidden
的值为 true, 反之为 false。最为重要的是hidden
的值,可以通过调用 isHidden()
函数获取。
那么结合上述知识点,我们能推导出:
- 因为 Fragment_1 的
隐藏状态
从可见转为了不可见
,所以其onHiddenChanged
函数被调用,同时hidden
的值为 true。 - 同理对于 Fragment_2 ,因为其
隐藏状态
从不可见转为了可见
,所以其 hidden 值为 false。 - 对于 Fragment_3 ,因为其隐藏状态从始至终都没有发生变化,所以其 onHiddenChanged 函数并不会调用。
嗯,好像有点眉目了。不急,我们继续看下面的例子。
show Fragment_3 并 hide 其他 Fragment ,对应生命周期函数调用如下所示:

从图中,我们可以看出,确实只有隐藏状态
发生了改变的 Fragment 其 onHiddenChanged
函数才会调用,那么结合以上知识点,我们能得出如下重要结论:
只要通过 show+hide
方式控制 Fragment 的显隐,那么在第一次初始化后,Fragment 任何的生命周期方法都不会调用,只有 onHidden