super.onHiddenChanged(hidden)
isVisibleToUser = !hidden
judgeLazyInit()
}
private fun judgeLazyInit() {
if (!isLoaded && !isHidden) {
lazyInit()
isLoaded = true
}
}
override fun onDestroyView() {
super.onDestroyView()
isLoaded = false
}
//懒加载方法
abstract fun lazyInit()
}
该懒加载的实现,是在
onResume
方法中操作,当然你可以在其他生命周期函数中控制。但是建议在该方法中执行懒加载。
ViewPager+Fragment 模式下的老方案
使用传统方式处理 ViewPager 中 Fragment 的懒加载,我们需要控制 setUserVisibleHint(boolean isVisibleToUser)
函数,该函数的声明如下所示:
public void setUserVisibleHint(boolean isVisibleToUser) {}
该函数与之前我们介绍的 onHiddenChanged()
作用非常相似,都是通过传入的参数值来判断当前 Fragment 是否对用户可见,只是 onHiddenChanged()
是在 add+show+hide
模式下使用,而 setUserVisibleHint
是在 ViewPager+Fragment 模式下使用。
在本节中,我们用 FragmentPagerAdapter + ViewPager
为例,向大家讲解如何实现 Fragment 的懒加载。
注意:在本例中没有调用
setOffscreenPageLimit
方法去设置 ViewPager 预缓存的 Fragment 个数。默认情况下 ViewPager 预缓存 Fragment 的个数为1
。
初始化 ViewPager 查看内部 Fragment 生命周期函数调用情况:
观察上图,我们能发现 ViePager 初始化时,默认会调用其内部 Fragment 的 setUserVisibleHint 方法,因为其预缓存 Fragment 个数为 1
的原因,所以只有 Fragment_1 与 Fragment_2 的生命周期函数被调用。
我们继续切换到 Fragment_2,查看各个Fragment的生命周期函数的调用变化。如下图所示:
观察上图,我们同样发现 Fragment 的 setUserVisibleHint 方法被调用了,并且 Fragment_3 的一系列生命周期函数被调用了。继续切换到 Fragment_3:
观察上图可以发现,Fragment_3 调用了 setUserVisibleHint 方法,继续又切换到 Fragment_1,查看调用函数的变化:
因为之前在切换到 Fragment_3 时,Frafgment_1 已经走了 onDestoryView(图二,蓝色标记处) 方法,所以 Fragment_1 需要重新走一次生命周期。
那么结合本节的三幅图,我们能得出以下结论:
-
使用 ViewPager,切换回上一个 Fragment 页面时(已经初始化完毕),不会回调任何生命周期方法以及onHiddenChanged(),只有 setUserVisibleHint(boolean isVisibleToUser) 会被回调。
-
setUserVisibleHint(boolean isVisibleToUser) 方法总是会优先于 Fragment 生命周期函数的调用。
所以如果我们想对 ViewPager 中的 Fragment 懒加载,我们需要这样处理:
abstract class LazyFragment : Fragment() {
/**
- 是否执行懒加载
*/
private var isLoaded = false
/**
- 当前Fragment是否对用户可见
*/
private var isVisibleToUser = false
/**
-
当使用ViewPager+Fragment形式会调用该方法时,setUserVisibleHint会优先Fragment生命周期函数调用,
-
所以这个时候就,会导致在setUserVisibleHint方法执行时就执行了懒加载,
-
而不是在onResume方法实际调用的时候执行懒加载。所以需要这个变量
*/
private var isCallResume = false
override fun onResume() {
super.on