原因分析
在使用ViewPager+FragmentPagerAdapter時候逼庞,更新Fragment里數(shù)據(jù)是不起作用俱诸,F(xiàn)ragmentPagerAdapter添加Fragment、減少Fragment维雇、切換順序時淤刃,前面的Fragment內(nèi)容更新不起作用。這是因為
FragmentPagerAdapter的創(chuàng)建fragment機制所導(dǎo)致的吱型。定位到FragmentPagerAdapter源碼逸贾,其中創(chuàng)建更新fragment的方法是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;
}
instantiateItem方法中會根據(jù)itemId生成name來查找fragment是否已經(jīng)存在,如果不存在則創(chuàng)建新的fragment津滞,否則不創(chuàng)建新的fragment铝侵。
itemId是通過getItemId方法獲取的,那么触徐,定位到getItemId方法:
public long getItemId(int position) {
return position;
}
getItemId僅僅只是返回當(dāng)前的position咪鲜。這就是FragmentPagerAdapter無法更新的原因了。比如FragmentPagerAdapter有3個fragment锌介, 那么通過getItemId獲取到的itemId就為0, 1嗜诀, 2猾警,這時變更數(shù)據(jù),把第一個fragment的數(shù)據(jù)與第三個fragment交換隆敢,但getItemId獲取到的itemId仍是0, 1发皿, 2,instantiateItem方法里就不會去執(zhí)行新的創(chuàng)建或更新數(shù)據(jù)了拂蝎。這就是FragmentPagerAdapter無法更新數(shù)據(jù)的原因了穴墅。
解決方案
1、暴力移除fragment
ist<Fragment> fragments = getSupportFragmentManager().getFragments();
for (int i = fragments.size() - 1; i >= 0; i--) {
getSupportFragmentManager().beginTransaction().remove(fragments.get(0));
}
2温自、重寫instantiateItem方法
3玄货、重寫getItemId方法
@Override
public long getItemId(int position) {
// 獲取當(dāng)前數(shù)據(jù)的hashCode
int hashCode = data.get(position).hashCode();
return hashCode;
}