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方法已经被谷歌废弃,官方推荐使用第二种方法!

你可能感兴趣的:(Fragment的两种懒加载方式)