美文网首页
Fragment的getChildFragmentManager

Fragment的getChildFragmentManager

作者: Cursor_fei | 来源:发表于2017-12-27 11:15 被阅读54次

    前提:

    这次项目中采用了在fragment中添加了一个viewpager的形式,viewpager中切换的是fragment。

    BUG:

    退出了那个包含viewpager的fragment并重新进入,切换viewpager时,不调用fragmentpageradapter适配器的getItem()方法,在显示上,出现viewpager的显示数量增多、显示数据不正确(这个情况只在初始化fragment时,需要传递参数的情况)的情况。

    调试:

    fragmentpageradapter的instantiateItem(ViewGroup container, int position)方法,在调用的时候做了优化处理:

    public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
    
        final long itemId = getItemId(position);
    
        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId));
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }
    
        return fragment;
    }
    

    以上代码中,会先判断是否已经加载过这个fragment,如果加载过,就只进行attach操作,不会进行实例化,这样可以节约资源。在上面的前提下,debug到这时第二次进入到fragment后,切换内部的fragment时,在此处mFragmentManager.findFragmentByTag(name);方法返回值都不为空,所以导致了上面提到的BUG。

    解决:

    在实例化FragmentPagerAdapter类时,需要传递两个参数,将第一个参数设置为getChildFragmentManager()而非getFragmentManager()即可解决问题。

    fragment源码中有getFragmentManager()的说明:

    /**
         * Return the FragmentManager for interacting with fragments associated
         * with this fragment's activity.  Note that this will be non-null slightly
         * before {@link #getActivity()}, during the time from when the fragment is
         * placed in a {@link FragmentTransaction} until it is committed and
         * attached to its activity.
         *
         * <p>If this Fragment is a child of another Fragment, the FragmentManager
         * returned here will be the parent's {@link #getChildFragmentManager()}.
         */
        final public FragmentManager getFragmentManager() {
            return mFragmentManager;
        }
    

    可以理解为:
    getFragmentManager()是所在fragment 父容器的碎片管理,
    getChildFragmentManager()是在fragment 里面子容器的碎片管理。

    相关文章

      网友评论

          本文标题:Fragment的getChildFragmentManager

          本文链接:https://www.haomeiwen.com/subject/fbaygxtx.html