前段時間在版本迭代里,一個activity中嵌套了多個fragment,當其中一個或多個數據發生變化時,通過pagerAdapter的notifyDataSetChanged方法去更新或者清空fragment集合重新給fragment設置數據并添加至集合時,最后結果都不能達到預期,數據還是原來的數據。
于是,我們一起來看看原因所在,看看FragmenPagerAdaptere的instantiateItem方法源碼就明白了():
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;
原來它會先去FragmentManager里面去查找有沒有緩存該fragment,如果有就直接使用,如果沒有才會觸發fragmentpageadapter的getItem方法獲取一個fragment。所以你更新的fragmentList集合是沒有作用的,即使清除fragment集合也是沒有用的,因為緩存依舊在,效果仍不達啊,所以我們需要去清除FragmentManager里面緩存的fragment,或者說替換了它,我們只需重寫它的instantiateItem方法:
public Object instantiateItem(ViewGroup container, int position) {
//拿到緩存的fragment,如果沒有緩存的,就新建一個,新建發生在fragment的第一次初始化時
RecyclerFragment f = (RecyclerFragment) super.instantiateItem(container, position);
String fragmentTag = f.getTag();
if (f != getItem(position)) {
//如果是新建的fragment,f 就和getItem(position)是同一個fragment,否則進入下面
FragmentTransaction ft =mFm.beginTransaction();
//移除舊的fragment
ft.remove(f);
//換成新的fragment
f =getItem(position);
//添加新fragment時必須用前面獲得的tag
ft.add(container.getId(), f, fragmentTag);
ft.attach(f);
ft.commitAllowingStateLoss();
}
return f;
}