FragmentPagerAdapter皿伺、FragmentStatePagerAdapter和FragmentStateAdapter的區(qū)別你知道嘛

前段時(shí)間在給公司項(xiàng)目做優(yōu)化,換用了ViewPager盒粮,可以左右切換頁面鸵鸥,交互更順滑,改完之后發(fā)現(xiàn)Fragment總是不復(fù)用,每次切換回來會(huì)重復(fù)走onCreateView()onDestroyView()生命周期妒穴?宋税??這咋能行呢讼油,于是就在onCreateView()做了簡單的判斷杰赛,因?yàn)轫?xiàng)目用的是ViewBinding,所以就ViewBinding不為空就直接返回ViewBinding.getRoot()了矮台。這幾天在看Android JetpackViewPager2發(fā)現(xiàn)多了個(gè)FragmentStateAdapter用法比之前簡單不少:

class CollectionDemoFragment : Fragment() {
    // When requested, this adapter returns a DemoObjectFragment,
    // representing an object in the collection.
    private lateinit var demoCollectionAdapter: DemoCollectionAdapter
    private lateinit var viewPager: ViewPager2

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.collection_demo, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        demoCollectionAdapter = DemoCollectionAdapter(this)
        viewPager = view.findViewById(R.id.pager)
        viewPager.adapter = demoCollectionAdapter
    }
}
//重點(diǎn)在這里 就重寫了兩個(gè)方法
class DemoCollectionAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
    override fun getItemCount(): Int = 100

    override fun createFragment(position: Int): Fragment {
        // Return a NEW fragment instance in createFragment(int)
        val fragment = DemoObjectFragment()
        fragment.arguments = Bundle().apply {
            // Our object is just an integer :-P
            putInt(ARG_OBJECT, position + 1)
        }
        return fragment
    }
}

然后興沖沖的給項(xiàng)目安排上乏屯,感覺自己又跟上大佬的腳步了,可是無意間看到居然沒有重寫走onCreateView()onDestroyView()生命周期(順便提一下FragmentManager.FragmentLifecycleCallbacks可以監(jiān)控Fragment生命周期類似Activity生命周期監(jiān)聽Application.ActivityLifecycleCallbacks)瘦赫,本著打破砂鍋問到底的原則詳細(xì)了解了下FragmentPagerAdapter辰晕、FragmentStatePagerAdapter和FragmentStateAdapter三者的區(qū)別。

FragmentPagerAdapter

源于androidx.fragment确虱,繼承于PagerAdapter含友,已于androidx.fragment 1.3.0版本廢棄,重點(diǎn)在instantiateItem()

    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        final long itemId = getItemId(position);

        // Do we already have this fragment?
        //這個(gè)fragment已經(jīng)存在過?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        //已經(jīng)存在執(zhí)行attach(fragment);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {//沒有存在通過getItem()獲取
            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);
            if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
                mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED);
            } else {
                fragment.setUserVisibleHint(false);
            }
        }
        return fragment;
    }

可以看到FragmentPagerAdapter的處理邏輯是存在這個(gè)Fragment就會(huì)執(zhí)行attach()必然會(huì)重走一遍Fragment的生命周期校辩,并不會(huì)復(fù)用之前創(chuàng)建的Fragment窘问,顯然跟我們要的不符,這個(gè)時(shí)候我們就用到了FragmentStatePagerAdapter

FragmentStatePagerAdapter

同樣源于androidx.fragment召川,繼承于PagerAdapter南缓,已于androidx.fragment 1.3.0版本廢棄,同樣我們也看一下instantiateItem()里的實(shí)現(xiàn)

    @Override
    public Object instantiateItem(@NonNull 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);
        if (mBehavior == BEHAVIOR_SET_USER_VISIBLE_HINT) {
            fragment.setUserVisibleHint(false);
        }

        mFragments.set(position, fragment);
        mCurTransaction.add(container.getId(), fragment);

        if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
            mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED);
        }

        return fragment;
    }

可以看到FragmentStatePagerAdapter有緩存Fragment隊(duì)列荧呐,當(dāng)Fragment實(shí)例化之后會(huì)取已經(jīng)實(shí)例化的Fragment汉形,并且多了個(gè)SavedState的邏輯,用于保存Fragment的狀態(tài)(滑過后會(huì)保存當(dāng)前界面倍阐,以及下一個(gè)界面和上一個(gè)界面(如果有)概疆,最多保存3個(gè),其他會(huì)被銷毀掉峰搪,可以通過ViewPager的setOffscreenPageLimit(int limit)設(shè)置)
但在回調(diào)onDestroy()方法之前會(huì)回調(diào)onSaveInstanceState(Bundle outState)方法來保存Fragment的狀態(tài)岔冀,下次Fragment顯示時(shí)通過onCreate(Bundle savedInstanceState)把存儲(chǔ)的狀態(tài)值取出來,FragmentStatePagerAdapter比較適合頁面比較多的情況概耻。

FragmentStateAdapter

源于ViewPager2FragmentPagerAdapterFragmentStatePagerAdapter的替換類使套,繼承于RecyclerView.Adapter
FragmentStatePagerAdapter相似鞠柄,該適配器實(shí)現(xiàn)了StatefulAdapter用于保存Fragment的狀態(tài)侦高。

private void ensureFragment(int position) {
        long itemId = getItemId(position);
        if (!mFragments.containsKey(itemId)) {
            // TODO(133419201): check if a Fragment provided here is a new Fragment
            Fragment newFragment = createFragment(position);
            newFragment.setInitialSavedState(mSavedStates.get(itemId));
            mFragments.put(itemId, newFragment);
        }
    }

可以看到FragmentStateAdapter同樣有緩存Fragment隊(duì)列

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市厌杜,隨后出現(xiàn)的幾起案子奉呛,更是在濱河造成了極大的恐慌计螺,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞧壮,死亡現(xiàn)場(chǎng)離奇詭異登馒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)咆槽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門陈轿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人罗晕,你說我怎么就攤上這事济欢。” “怎么了小渊?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茫叭。 經(jīng)常有香客問我酬屉,道長,這世上最難降的妖魔是什么揍愁? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任呐萨,我火速辦了婚禮,結(jié)果婚禮上莽囤,老公的妹妹穿的比我還像新娘谬擦。我一直安慰自己,他們只是感情好朽缎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布惨远。 她就那樣靜靜地躺著,像睡著了一般话肖。 火紅的嫁衣襯著肌膚如雪北秽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天最筒,我揣著相機(jī)與錄音贺氓,去河邊找鬼。 笑死床蜘,一個(gè)胖子當(dāng)著我的面吹牛辙培,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播邢锯,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼扬蕊,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了弹囚?” 一聲冷哼從身側(cè)響起厨相,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后蛮穿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庶骄,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年践磅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了单刁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡府适,死狀恐怖羔飞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情檐春,我是刑警寧澤逻淌,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站疟暖,受9級(jí)特大地震影響卡儒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜俐巴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一骨望、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧欣舵,春花似錦擎鸠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至准验,卻和暖如春赎线,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背糊饱。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工垂寥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人另锋。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓滞项,卻偏偏與公主長得像,于是被迫代替她去往敵國和親夭坪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子文判,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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