FragmentPagerAdapter 和FragmentStatePagerAdapter區(qū)別

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ū)別:

  1. FragmentPagerAdapter 中每一個(gè)Fragment都長(zhǎng)存在與內(nèi)存中筛欢,適用于比較固定的少量的Fragment浸锨。FragmentPagerAdapter 在我們切換Fragment過(guò)程中不會(huì)銷毀Fragment,只是調(diào)用事務(wù)中的detach方法版姑。而在detach方法中只會(huì)銷毀Fragment中的View柱搜,而不會(huì)銷毀Fragment對(duì)象。
  2. 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直接銷毀掉。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末夭拌,一起剝皮案震驚了整個(gè)濱河市魔熏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鸽扁,老刑警劉巖蒜绽,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異桶现,居然都是意外死亡躲雅,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門骡和,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)相赁,“玉大人,你說(shuō)我怎么就攤上這事慰于∨タ疲” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵婆赠,是天一觀的道長(zhǎng)绵脯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)休里,這世上最難降的妖魔是什么蛆挫? 我笑而不...
    開(kāi)封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮份帐,結(jié)果婚禮上璃吧,老公的妹妹穿的比我還像新娘楣导。我一直安慰自己废境,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著噩凹,像睡著了一般巴元。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上驮宴,一...
    開(kāi)封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天逮刨,我揣著相機(jī)與錄音,去河邊找鬼堵泽。 笑死修己,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的迎罗。 我是一名探鬼主播睬愤,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纹安!你這毒婦竟也來(lái)了尤辱?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤厢岂,失蹤者是張志新(化名)和其女友劉穎光督,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體塔粒,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡结借,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卒茬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片映跟。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖扬虚,靈堂內(nèi)的尸體忽然破棺而出努隙,到底是詐尸還是另有隱情,我是刑警寧澤辜昵,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布荸镊,位于F島的核電站,受9級(jí)特大地震影響堪置,放射性物質(zhì)發(fā)生泄漏躬存。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一舀锨、第九天 我趴在偏房一處隱蔽的房頂上張望岭洲。 院中可真熱鬧,春花似錦坎匿、人聲如沸盾剩。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)告私。三九已至屎暇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驻粟,已是汗流浹背根悼。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蜀撑,地道東北人挤巡。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像酷麦,于是被迫代替她去往敵國(guó)和親玄柏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容