FragmentPagerAdapter中Fragment不能重新整理問題
阿新 • • 發佈:2019-01-11
FragmentPagerAdapter中Fragment不重新整理終極解決方案:
最近手裡一個專案有個下拉重新整理的功能:(下拉重新整理要更新所有fragment頁面中的資料),在網上看了很多部落格都沒解決問題。最後自己研究了一下原始碼,既然奇蹟般的解決了!
專案主要結構如下圖(版權問題就直接寫了個demo):
下面是我的解決方案:
我們先開啟FragmentPagerAdapter的原始碼去檢視裡面的instantiateItem()方法:
@Override
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;
}
他會先去FragmentManager裡面去查詢有沒有相關的fragment如果有就直接使用Manage中快取的fragment,如果沒有才會觸發FragmentPagerAdatper的getItem方法獲取一個fragment。所以這個時候你直接去更新fragments集合是沒有作用的。
這個時候我們要做的是清除FragmentManager裡面全部快取的fragment。然後更新fragment後再重新載入。
怎麼清除FragmentManager中快取是現在的問題,當我看FragmentPagerAdapter時,我發現裡面有個makeFragmentName()方法:原始碼如下:
private static String makeFragmentName(int viewId, long id) {
return "android:switcher:" + viewId + ":" + id;
}
根據方法名字可以猜測應該得到fragment的名字。當我們得到fragment名字了就可以直接通過名字來找到具體快取的fragment了;這個時候我只需要重寫FragmentPagerAdapter中的instantiateItem();
下面貼上最終程式碼(註釋都很詳細就不做過多解釋了)
/**
* 時 間: 2017/4/15
* 作 者: 鄭亮
* Q Q : 1023007219
*/
public class BaseFragmentAdapter extends FragmentPagerAdapter {
private List<BaseFragment> fragments;
private FragmentManager fm;
public BaseFragmentAdapter(FragmentManager fm,List<BaseFragment> fragments) {
super(fm);
this.fm = fm;
this.fragments= fragments;
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
FragmentTransaction ft = fm.beginTransaction();
for (int i = 0; i < getCount(); i++) {//通過遍歷清除所有快取
final long itemId = getItemId(i);
//得到快取fragment的名字
String name = makeFragmentName(container.getId(), itemId);
//通過fragment名字找到該物件
BaseFragment fragment = (BaseFragment) fm.findFragmentByTag(name);
if (fragment != null) {
//移除之前的fragment
ft.remove(fragment);
}
}
//重新新增新的fragment:最後記得commit
ft.add(container.getId(), getItem(position)).attach(getItem(position)).commit();
return getItem(position);
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
/**
* 得到快取fragment的名字
* @param viewId
* @param id
* @return
*/
private String makeFragmentName(int viewId, long id) {
return "android:switcher:" + viewId + ":" + id;
}
}