这两天遇到一个问题,发现了使用FragmentPagerAdapter的时候,切换不同Fragment子类会导致只用前面加入的Fragment。然后上网搜索相关问题发现还是没有,所以自己看了下源码发现了在FragmentPagerAdapter中的缓存实现是这样的:
当切换Fragment的时候
销毁item:
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
+ " v=" + ((Fragment)object).getView());
mCurTransaction.detach((Fragment)object);
}
他会调用mCurTransaction.detach((Fragment)object);因为是detach所以只会销毁view而不会销毁当前fragment。
创建item:
@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;
}
它会根据getItemId(position)方法来获取id,从而获取到fragment,没有fragment的话将会调用getItem方法获取你的新的fragment,mCurTransaction添加fragment。而getItemId只会根据你的position(fragments当前位置)来作为id使用。
那么解决这个的思路就是:我通过重写getItemId让每个fragment都有不同的id,那么当我用不同的Fragment子类来重新赋值fragments时候,就会让FragmentPagerAdapter给我重新添加fragment,达到显示正常的目的
具体代码
mAdapter = object : FragmentPagerAdapter(fragmentManager) {
override fun getItemId(position: Int): Long {
return fragments[position].hashCode().toLong()
}
override fun getItem(position: Int): Fragment {
return fragments[position]
}
override fun getCount(): Int {
return titles.size
}
override fun getPageTitle(position: Int): CharSequence {
return titles[position]
}
}
关键代码在getItemId处,返回fragment的哈希码让他们都有不同的缓存,这样在比较少的fragment时候就会实现我的目的。