fragment的getChildFragmentManager與getFragmentManager方法

前提:這次項目中採用了在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  裏面子容器的碎片管理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章