【转载】在ViewPager中的Fragment懒加载

原作者:炙炎gg
链接:https://www.jianshu.com/p/9eb1c379f3e7#
來源:简书

对于原文的解析在某些方面做了进一步分析,代码如下

/**
 * Created by LinLin on 2018/6/6.
 * 在viewpager中使用Fragment,Fragment的成员变量是不会销毁的
 * <p>
 * 利用Fragment的生命周期进行懒加载 ,预加载使用ViewStub代替真实View
 */

public abstract class MagicLifeLazyFragment extends Fragment
{
    /**
     * 根view,升格为成员变量保持不会销毁
     */
    private View mRootView;

    /**
     * 用于回调的,用户是否可见参数,升格为成员变量保持不会销毁
     */
    private boolean isVisibleToUser;

    /**
     * 第一次加载
     */
    private boolean isFirstLoad;

    /**
     * view是否已经创建完毕
     */
    private boolean isViewCreated;

    /**
     * 第一次加载的占位图
     */
    private ViewStub mViewStub;

    @Nullable
    @Override
    public final View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
    {
        /**
         * 判断根view是否为空。
         * 为空代表第一次加载;
         * 不为空代表曾经加载过,这次是重复加载,因为是成员变量,不会被销毁,所以直接返回
         * */
        if (null != mRootView)
        {
            isViewCreated = true;//设为view已加载
            return mRootView;
        }

        /**
         * 第一次加载,使用占位图,使用FrameLayout作为根view,包裹一个ViewStub
         * */

        final Context context = inflater.getContext();
        FrameLayout root = new FrameLayout(context);
        mViewStub = new ViewStub(context, getResId());

        root.addView(mViewStub, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
        root.setLayoutParams(new ViewGroup.MarginLayoutParams(ViewGroup.MarginLayoutParams.MATCH_PARENT, ViewGroup.MarginLayoutParams.MATCH_PARENT));

        mRootView = root;//作为根view
        isViewCreated = true;//设为view已加载


        if (isVisibleToUser)
        {
            realLoad();
        }

        return mRootView;
    }

    @Override
    public void onDestroyView()
    {
        isViewCreated = false;
        super.onDestroyView();
    }

    /**
     * 关于这个方法的被回调的地方有:
     * 1、FragmentPagerAdapter 的 public Object instantiateItem(ViewGroup container, int position)方法里
     *      if (fragment != mCurrentPrimaryItem) {
     *          fragment.setMenuVisibility(false);
     *          fragment.setUserVisibleHint(false);
     *      }
     * 初始化的时候会设为false
     * 2、 FragmentPagerAdapter 的 public void setPrimaryItem(ViewGroup container, int position, Object object) 方法里
     *      if (fragment != mCurrentPrimaryItem) {
     *          if (mCurrentPrimaryItem != null) {
     *              mCurrentPrimaryItem.setMenuVisibility(false);
     *              mCurrentPrimaryItem.setUserVisibleHint(false);
     *          }
     *          if (fragment != null) {
     *              fragment.setMenuVisibility(true);
     *              fragment.setUserVisibleHint(true);
     *          }
     *          mCurrentPrimaryItem = fragment;
     *      }
     * 而上述方法都会被viewpager回调。
     * 举个例子:有FragmentA,FragmentB,FragmentC三个,当前显示的是FragmentB
     * 那么初始化顺序是 FragmentA,FragmentB,FragmentC 分别设 setUserVisibleHint(false);
     * 然后选择FragmentB为当前页面,viewpager调用setPrimaryItem方法,FragmentB设 setUserVisibleHint(true);
     * 由于是第一次加载所以mCurrentPrimaryItem==null,否则旧的Fragment也会设一次setUserVisibleHint(false);
     * 结合Fragment的生命周期得知:当isVisibleToUser为true以及根view创建完毕即可加载数据
     */
    @Override
    public final void setUserVisibleHint(boolean isVisibleToUser)
    {
        super.setUserVisibleHint(isVisibleToUser);
        this.isVisibleToUser=isVisibleToUser;
        if (isViewCreated && isVisibleToUser)
        {
            realLoad();
        }
    }

    /**
     * 真实加载数据
     * 控制只允许加载一次
     */
    private void realLoad()
    {
        if (isFirstLoad)
        {
            return;
        }

        isFirstLoad = true;
        onRealViewLoaded(mViewStub.inflate());
    }


    /**
     * 获取真正的数据视图
     */
    protected abstract int getResId();

    /**
     * 当视图真正加载时调用
     */
    protected abstract void onRealViewLoaded(View view);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值