FragmentPagerAdapter 和FragmentStatePagerAdapter 一樣都是一個(gè)abstract抽象類量愧,并且都繼承于PagerAdapter色建,由于PagerAdapter里面有一個(gè)getCount()抽象方法:
/**
* Return the number of views available.
*/
public abstract int getCount();
而FragmentPagerAdapter和FragmentStatePagerAdapter 里面都有一個(gè)getItem(int position) 抽象方法:
/**
* Return the Fragment associated with a specified position.
*/
public abstract Fragment getItem(int position);
所以在使用的時(shí)候要重寫這兩個(gè)方法:
class MyAdapter extends FragmentPagerAdapter{
public MyAdapter(FragmentManager fm){
super(fm);
}
@Override
public Fragment getItem(int position) {
return ArrayListFragment.newInstance(position);
}
@Override
public int getCount() {
return NUM_ITEMS;
}
}
其中 getCount()返回的是ViewPager頁(yè)面的數(shù)量多柑,getItem()返回的是要顯示的fragent對(duì)象骏融。
但是這兩個(gè)PagerAdapter有什么區(qū)別呢箭跳?可以通過(guò)源碼來(lái)分析析苫。
源碼分析
instantiateItem
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;
}
FragmentStatePagerAdapter 的instantiateItem():
@Override
public Object instantiateItem(ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return f;
}
}
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
Fragment fragment = getItem(position);
if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
if (mSavedState.size() > position) {
Fragment.SavedState fss = mSavedState.get(position);
if (fss != null) {
fragment.setInitialSavedState(fss);
}
}
while (mFragments.size() <= position) {
mFragments.add(null);
}
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
mFragments.set(position, fragment);
mCurTransaction.add(container.getId(), fragment);
return fragment;
}
可以看出這兩個(gè)區(qū)別在FragmentStatePagerAdapter 里面首先通過(guò)mFragments的集合判斷是否含有Framgnet兜叨,如果有的話則直接返回Fragment。而FragmentPagerAdapter 并沒(méi)有這一步衩侥。FragmentPagerAdapter 是直接從固定里面獲取国旷。
而FragmentStatePagerAdapter 是用一個(gè) ArrayList<Fragment>來(lái)存儲(chǔ)所有的Fragment,從這里也可以看出這兩者的區(qū)別茫死,F(xiàn)ragmentPagerAdapter 適用于固定少量的Fragment跪但。而FragmentStatePagerAdapter 較多Fragment的場(chǎng)景。
destroyItem
FragmentPagerAdapter->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);
}
FragmentStatePagerAdapter ->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, fragment.isAdded()
? mFragmentManager.saveFragmentInstanceState(fragment) : null);
mFragments.set(position, null);
mCurTransaction.remove(fragment);
}
從源碼看出在destroyItem銷毀的時(shí)候峦萎,F(xiàn)ragmentPagerAdapter是調(diào)用detach()方法屡久,將Fragment的id和宿主解綁,其實(shí)并沒(méi)有把Fragment銷毀爱榔。所以FragmentPagerAdapter中的Fragment一直存在內(nèi)存中被环。
而FragmentStatePagerAdapter 是直接remove掉Fragment,直接銷毀Fragment详幽。
總結(jié)
FragmentPagerAdapter 和FragmentStatePagerAdapter區(qū)別:
- FragmentPagerAdapter 中每一個(gè)Fragment都長(zhǎng)存在與內(nèi)存中筛欢,適用于比較固定的少量的Fragment浸锨。FragmentPagerAdapter 在我們切換Fragment過(guò)程中不會(huì)銷毀Fragment,只是調(diào)用事務(wù)中的detach方法版姑。而在detach方法中只會(huì)銷毀Fragment中的View柱搜,而不會(huì)銷毀Fragment對(duì)象。
- FragmentStatePagerAdapter中實(shí)現(xiàn)將只保留當(dāng)前頁(yè)面剥险,當(dāng)頁(yè)面離開(kāi)視線后冯凹,就會(huì)被消除,釋放其資源炒嘲。而在頁(yè)面需要顯示時(shí)宇姚,生成新的頁(yè)面。在較多的Fragment的時(shí)候?yàn)榱藴p少內(nèi)存可適用夫凸。FragmentStatePagerAdapter在我們切換Fragment浑劳,會(huì)把前面的Fragment直接銷毀掉。