AndroidX之前的Fragment懒加载
在AndroidX之前,Fragment的使用有两种方式:
使用ViewPager+Fragment模式
通过FragmentTransaction控制Fragment的使用
1.AndroidX之前ViewPager模式的懒加载
分析:
由于ViewPager的缓存机制offscreenPageLimit始终>=1,所以ViewPager会缓存布局屏幕外的Fragment>=1个,被缓存的屏幕外的Fragment也会像屏幕可见的Fragment一样执行生命周期到onResume,并且在用户滑动后缓存的Fragment由不可见到可见时并不会调用onResume。根据ViewPager调用Fragment的方法顺序:
setUserVisibleHint->onAttach->onCreate->onCreateView->onViewCreated->onActivityCreated->onStart->onResume
所以,在androidX之前,ViewPager模式的懒加载方式是:
对于第一个可见的Fragment,在onResume方法中执行懒加载请求数据
对于缓存的Fragment由不可见到可见时,通过setUserVisibleHint方法中执行懒加载请求数据
abstract class LazyFragment {
// Fragment的数据是否加载过
private var isLoaded = false
// Fragment是否可见
private var isVisibleToUser = false
// 是否加载过onResume
private var isCallResume = false
override fun onResume() {
super.onResume()
isCallResume = true
checkLazy()
}
private fun checkLazy() {
if (!isLoaded && isVisibleToUser && isCallResume) {
lazyInit()
isLoaded = true
}
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
this.isVisibleToUser = isVisibleToUser
checkLazy()
}
override fun onDestroyView() {
super.onDestroyView()
isLoaded = false
isVisibleToUser = false
isCallResume = false
}
abstract fun lazyInit()
}
需要注意的是ViewPager嵌套加载,对于第二个加载的ViewPager的数据绑定一定要放在上一个Fragment的lazyInit懒加载方法中进行初始化。如下:
override fun lazyInit() {
view_pager?.apply {
adapter = FragmentLazyStatePageAdapter(
childFragmentManager,
generateTextFragments(4),
generateTextFragmentTitles(4)
)
}
tab_layout?.setupWithViewPager(view_pager)
}
2.AndroidX之前FragmentTransaction控制模式的懒加载
通过FrameLayout绑定Fragment时,我们要通过FragmentTransaction进行控制。
FragmentTransaction transaction = FragmentManager.beginTransaction();
// Fragment绑定FrameLayout
transaction.add(containerViewId, fragment, fgTag);
// 控制Fragment的显示/隐藏
transaction.show(fragment);
transaction.hide(fragment);
// 提交
transaction.commit();
对于一个FrameLayout绑定多个Fragment,并每次只显示一个,我们可以这样通过FragmentTransaction控制Fragment的行为,代码如下:
// FrameLayout绑定多个Fragment
private fun loadFragmentsTransaction(
@IdRes containerViewId: Int, showPosition: Int,
fragmentManager: FragmentManager, vararg fragments: Fragment) {
if (fragments.isNotEmpty()) {