原因分析
在使用ViewPager+FragmentPagerAdapter时候,更新Fragment里数据是不起作用,FragmentPagerAdapter添加Fragment、减少Fragment、切换顺序时,前面的Fragment内容更新不起作用。这是因为
FragmentPagerAdapter的创建fragment机制所导致的。定位到FragmentPagerAdapter源码,其中创建更新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方法中会根据itemId生成name来查找fragment是否已经存在,如果不存在则创建新的fragment,否则不创建新的fragment。
itemId是通过getItemId方法获取的,那么,定位到getItemId方法:
public long getItemId(int position) {
return position;
}
getItemId仅仅只是返回当前的position。这就是FragmentPagerAdapter无法更新的原因了。比如FragmentPagerAdapter有3个fragment, 那么通过getItemId获取到的itemId就为0, 1, 2,这时变更数据,把第一个fragment的数据与第三个fragment交换,但getItemId获取到的itemId仍是0, 1, 2,instantiateItem方法里就不会去执行新的创建或更新数据了。这就是FragmentPagerAdapter无法更新数据的原因了。
解决方案
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) {
// 获取当前数据的hashCode
int hashCode = data.get(position).hashCode();
return hashCode;
}