Fragment的两种懒加载方式
很多人会忽略Viewpager + fragment的懒加载,其实很重要,当用户不想看到的fragment你却提前加载好了,这就是性能的浪费。那么,目前fragment的懒加载已经出现两种方式。
第一种:也就是旧版懒加载,通过重写setUserVisibleHint(isVisibleToUser: Boolean)方法来获取fragment的显示状态来判断是否加载,但是这个方法会在onCreateView方法前调用,所以同时也要判断当前View是否已经创建完成
var hasLoad = false
var isViewInitiated = false
fun loadData() {
if (userVisibleHint && !hasLoad && isViewInitiated) {
// load
hasLoad = true
}
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
userVisibleHint = isVisibleToUser
loadData()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
isViewInitiated = true
loadData()
}
override fun onDestroyView() {
super.onDestroyView()
isViewInitiated = false // 注意考虑View被销毁,而Fragment对象还在
}
第二种:就是通过FragmentTransaction类的一个方法setMaxLifecycle(fragment, Lifecycle.State.RESUMED)。
当第二个参数为RESUMED的时候则这个fragment的生命周期会调用onResume()方法。
若为STARTED的时候则新建的Fragment生命周期在执行onActivityCreated()之后会继续执行onStrat() ,但不会执行onResume()!;而原先处于RESUME状态的则会执行onPause()。
在FragmentPagerAdapter适配器的构造函数FragmentPagerAdapter(@NonNull FragmentManager fm,int behavior)
第二个参数是一个行为状态,当你传入该类的常量BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT的时候,适配器就会帮你把显示的条目fragment进行setMaxLifecycle(fragment, Lifecycle.State.RESUMED)。其他未显示的条目fragment进行setMaxLifecycle(fragment, Lifecycle.State.STARTED)。
public Object instantiateItem(@NonNull ViewGroup container, int position) {
Fragment fragment = mFragmentManager.findFragmentByTag(name);
...
if (fragment != mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
// 看这里
if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED);
} else {
fragment.setUserVisibleHint(false);
}
}
return fragment;
}
@Override
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;
}
}
所以,我们可以通过以下代码进行懒加载
public ResourcesPagerAdapter(FragmentManager fm) {
super(fm,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
var hasLoad = false
fun loadData() {
if (hasLoad) {
// load
hasLoad = true
}
}
override fun onResume() {
super.onResume()
loadData()
}
最后,说明一下,第一种方法中的setUserVisibleHint方法已经被谷歌废弃,官方推荐使用第二种方法!