两个基于PagerAdapter的类,都是在ViewPager里面,每次生成Fragment时用到的,只是各自的侧重点不同,FragmentStatePagerAdapter侧重于对于在多页面中展示,需要每次都去处理生成新的Fragment,而FragmentPagerAdapter侧重于展示数量少的页面,对于将展示过的页面(Fragment)存储起来,再次加载时,直接调用内存中的Fragment以达到节省时间和资源的目的。
- FragmentPagerAdapter:
我们主要看一下在初始化Item时候调用到的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?
//判断请求的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);
//调用这个方法来生成新的Fragment
if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
mCurTransaction.add(container.getId(), fragment,
makeFragmentName(container.getId(), itemId));
//将新生成的Fragment存储起来,以便以后再次用到时,直接attach()
}
if (fragment != mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
}
return fragment;
}
然后我们再来看下getItem()方法:
/**
* Return the Fragment associated with a specified position.
*/
public abstract Fragment getItem(int position);
//这是一个抽象的方法,需要我们在使用时候自己去实现
最后是destroyItem()方法:
@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);
//这里是区别的重点 在销毁Item时候,FragmentPagerAdapter
//仅仅是调用了detach()方法,断开了连接,但是并没有真正的
//把Fragment消除掉。
}
detach()方法的调用,说明在使用FragmentPagerAdapter时候,只有消除整个adapter时候,才能将生成的Fragment都消除掉,不然就会直接在内存中。
2 .FragmentStatePagerAdapter
我们也来看下他的instantiateItem()方法:
@Override
public Object instantiateItem(ViewGroup container, int position) {
.
.
.
Fragment fragment = getItem(position);//同样在这里生成Fragment
.
.
.
return fragment;
}
getItem()方法也是一样的:
public abstract Fragment getItem(int position);
重点看destroyItem()方法:
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
+ " v=" + ((Fragment)object).getView());
while (mSavedState.size() <= position) {
mSavedState.add(null);
}
mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
mFragments.set(position, null);
mCurTransaction.remove(fragment);
//当销毁当前显示的页面时,调用了remove()方法,
//说明Fragment已经被销毁,资源已经被释放了。
//如果需要再次调用时候,需要去重新生成Fragment
}
两种都各自有适用的场景,选择合适的就好。
参考:
http://www.cnblogs.com/dancefire/archive/2013/01/02/why-notifydatasetchanged-does-not-work.html