年后最后一篇文章啦,在这里先祝大家新年快乐~最重要的抽中
全家福
,明年继续修福报🤣
以前处理 Fragment 的懒加载,我们通常会在 Fragment 中处理
setUserVisibleHint + onHiddenChanged
这两个函数,而在 Androidx 模式下,我们可以使用
FragmentTransaction.setMaxLifecycle()
的方式来处理 Fragment 的懒加载。
在本文章中,我会详细介绍不同使用场景下两种方案的差异。大家快拿好小板凳。一起来学习新知识吧!
本篇文章涉及到的 Demo,已上传至Github—->
传送门
AndroidxLazyLoad
项目自行测试。
观察上述例子,我们可以发现,使用了
BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
后,确实只有当前可见的 Fragment 调用了 onResume 方法。而导致产生这种改变的原因,是因为 FragmentPagerAdapter 在其
setPrimaryItem
方法中调用了
setMaxLifecycle
方法,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
public void setPrimaryItem (@NonNull ViewGroup container, int position, @NonNull Object object) { Fragment fragment = (Fragment)object; if (fragment != mCurrentPrimaryItem) { if (mCurrentPrimaryItem != null ) { mCurrentPrimaryItem.setMenuVisibility(false ); if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { if (mCurTransaction == null ) { mCurTransaction = mFragmentManager.beginTransaction(); } mCurTransaction.setMaxLifecycle(mCurrentPrimaryItem, Lifecycle.State.STARTED); } else { mCurrentPrimaryItem.setUserVisibleHint(false ); } } fragment.setMenuVisibility(true ); if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { if (mCurTransaction == null ) { mCurTransaction = mFragmentManager.beginTransaction(); } mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.RESUMED); } else { fragment.setUserVisibleHint(true ); } mCurrentPrimaryItem = fragment; } }
既然在上述条件下,只有实际可见的 Fragment 会调用 onResume 方法, 那是不是为我们提供了 ViewPager 下实现懒加载的新思路呢?也就是我们可以这样实现 Fragment 的懒加载:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
abstract class LazyFragment : Fragment () { private var isLoaded = false override fun onResume () { super .onResume() if (!isLoaded) { lazyInit() Log.d(TAG, "lazyInit:!!!!!!!" ) isLoaded = true } } override fun onDestroyView () { super .onDestroyView() isLoaded = false } abstract fun lazyInit () }
ShowHideExt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
private fun loadFragmentsTransaction ( @IdRes containerViewId: Int , showPosition: Int , fragmentManager: FragmentManager , vararg fragments: Fragment ) { if (fragments.isNotEmpty()) { fragmentManager.beginTransaction().apply { for (index in fragments.indices) { val fragment = fragments[index] add(containerViewId, fragment, fragment.javaClass.name) if (showPosition == index) { setMaxLifecycle(fragment, Lifecycle.State.RESUMED) } else { hide(fragment) setMaxLifecycle(fragment, Lifecycle.State.STARTED) } } }.commit() } else { throw IllegalStateException( "fragments must not empty" ) } } private fun showHideFragmentTransaction (fragmentManager: FragmentManager , showFragment: Fragment ) { fragmentManager.beginTransaction().apply { show(showFragment) setMaxLifecycle(showFragment, Lifecycle.State.RESUMED) val fragments = fragmentManager.fragments for (fragment in fragments) { if (fragment != showFragment) { hide(fragment) setMaxLifecycle(fragment, Lifecycle.State.STARTED) } } }.commit() }
上述代码的实现也非常简单:
将需要显示的 Fragment ,在调用 add 或 show 方法后,
setMaxLifecycle(showFragment, Lifecycle.State.RESUMED)
将需要隐藏的 Fragment ,在调用 hide 方法后,
setMaxLifecycle(fragment, Lifecycle.State.STARTED)
结合上述操作模式,查看使用 setMaxLifecycle 后,Fragment 生命周期函数调用的情况。
add Fragment_1、Fragment_2、Fragment_3,并 hide Fragment_2,Fragment_3
:
show Fragment_2,hide 其他 Fragment:
show Fragment_3 hide 其他 Fragment:
参考上图,好像真的也能处理懒加载!!!!!美滋滋
AndroidxLazyLoad
,大家可以结合项目查看Log日志。