首頁管理 Fragment 方式

我見過很多種裆操,寫也過很多種 - 首頁管理 Fragment ,這里我覺得有必要整理一下思路腰湾,為依然不是很順手的朋友提供下思路

1. Fragment 切換方式

首頁的 Fragment 是要求無縫切換的勤家,換言之就是不能卡健民,要一瞬間完成狮荔,有時產(chǎn)品還要加上一點小動畫效果

這里我們推薦 show/hide 這套組合,我們不用維護(hù) currentFragment 介粘,邏輯復(fù)雜轴合, 還容易出 bug ,最好的思路是遍歷 FragmentManager 碗短,看看誰當(dāng)前顯示者受葛,然后 hind,show 我們想要的就好偎谁,簡單干凈

    @Override
    protected void initListener() {
        super.initListener();
        navigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.menu_library:
                        switchFragment(libraryFragment);
                        break;
                    case R.id.menu_welfare:
                        if (welfareFragment == null) {
                            welfareFragment = new WelfareFragment();
                        }
                        switchFragment(welfareFragment);
                        break;
                    case R.id.menu_my:
                        if (myFragment == null) {
                            myFragment = new MyFragment();
                        }
                        switchFragment(myFragment);
                        break;
                }
                return true;
            }
        });
    private void switchFragment(Fragment fragment) {
        List<Fragment> fragments = fm.getFragments();
        for (Fragment f : fragments) {
            if (!f.equals(fragment) && !f.isHidden()) {
                fm.beginTransaction().hide(f).commit();
            }
        }
        if (fragment.isAdded()) {
            fm.beginTransaction().show(fragment).commit();
        } else {
            fm.beginTransaction().add(R.id.container, fragment).commit();
        }
    }

2. 第一個 Fragment 的處理

第一個 Fragment 我們直接在 onCreate 中初始化总滩,addFragment 進(jìn)去

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(bindLayout());

        libraryFragment = new LibraryFragment();
        addFragment(R.id.rootView, libraryFragment);
    }
    private void addFragment(int layoutID, Fragment fragment) {
        if (fragment.isAdded()) {
            fm.beginTransaction().show(fragment).commit();
        } else {
            fm.beginTransaction().add(layoutID, fragment).commit();
        }
    }

3. 首頁異常關(guān)閉處理

AC 若是由系統(tǒng)回收,屏幕旋轉(zhuǎn)或是異常關(guān)閉巡雨,會保存 app 中各種信息的闰渔,AC 堆棧數(shù)據(jù),F(xiàn)ragment 堆棧數(shù)據(jù)铐望。這里說首頁冈涧,首頁要是這樣被關(guān)閉然后由系統(tǒng)再起來,那么就會恢復(fù)之前我們在首頁添加的所有 Fragment 頁面正蛙,并且這樣頁面都在顯示督弓,也就是所謂的穿透 bug

樣子大概是這樣的:


若是這種情況,我們需要處理 onSaveInstanceState 和 onRestoreInstanceState 2個方法

3.1 onCreate 里面 savedInstanceState == null乒验,表示正常啟動

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化
        init();
        //根據(jù)傳入的Bundle對象判斷Activity是正常啟動還是銷毀重建
        if(savedInstanceState == null){
            //設(shè)置第一個Fragment默認(rèn)選中
            setFragment(0);
        }
    }

3.2 維護(hù)一個 fragmentId 或是一個 tag(可選項)

3.3 onSaveInstanceState 中保存當(dāng)前顯示的 Fragment 標(biāo)記愚隧,這個可以是上面自己記錄的fragmentId ,也可以遍歷 FragmentManage锻全,找到其中 !isHidden()狂塘,獲取其 TAG

@Override
    protected void onSaveInstanceState(Bundle outState) {
        //通過onSaveInstanceState方法保存當(dāng)前顯示的fragment
        outState.putInt("fragment_id",fragmentId);
        super.onSaveInstanceState(outState);
    }

3.4 onRestoreInstanceState 獲取所有的 Fragment ,然后顯示標(biāo)記的 鳄厌,hidden 其他的

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        FragmentManager mFragmentManager = getSupportFragmentManager();
        //通過FragmentManager獲取保存在FragmentTransaction中的Fragment實例
        mClothesFragment = (ClothesFragment)mFragmentManager
                .findFragmentByTag("clothes_fragment");
        mFoodFragment = (FoodFragment)mFragmentManager
                .findFragmentByTag("food_fragment");
        mHotelFragment = (HotelFragment)mFragmentManager
                .findFragmentByTag("hotel_fragment");
        //恢復(fù)銷毀前顯示的Fragment
        setFragment(savedInstanceState.getInt("fragment_id"));
    }

具體可以參考:


4. 配合 navigationBar 的優(yōu)秀寫法

這里使用的是開源 navigationBar : BottomNavigation

class HomeActivity : AppCompatActivity(){

    private var lastSelectedPosition = 0

    override fun onTabSelected(position: Int) {
        lastSelectedPosition = position
        replaceFragments(position)
    }

    private fun replaceFragments(position: Int) {
        supportFragmentManager.beginTransaction().apply {
            when (position) {
                0 -> replace(R.id.home_activity_frag_container, fragment1)
                1 -> replace(R.id.home_activity_frag_container, fragment2)
                2 -> replace(R.id.home_activity_frag_container, fragment3)
                3 -> replace(R.id.home_activity_frag_container, fragment4)
                4 -> replace(R.id.home_activity_frag_container, fragment5)
                else -> replace(R.id.home_activity_frag_container, fragment6)
            }
        }.commitAllowingStateLoss()
    }

}

這個寫法看著很干凈荞胡,當(dāng)然 replace 大家自己改改,換個方法


5. 其他

有位簡 友分享了自己的 fragment 切換代碼了嚎,只不過這個朋友比我們更對自己狠了一些泪漂,他想看看代碼通過設(shè)計能減到多少,玉石有了一篇: 記錄一次代碼演變過程——35行變24行新思,其實很不錯的窖梁,大家沒事都看看,當(dāng)我們平時對自己嚴(yán)要求之后都會有些閃光點的夹囚,記下來纵刘,因為你很快機(jī)會忘

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市荸哟,隨后出現(xiàn)的幾起案子假哎,更是在濱河造成了極大的恐慌瞬捕,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舵抹,死亡現(xiàn)場離奇詭異肪虎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)惧蛹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門扇救,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人香嗓,你說我怎么就攤上這事迅腔。” “怎么了靠娱?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵沧烈,是天一觀的道長。 經(jīng)常有香客問我像云,道長锌雀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任迅诬,我火速辦了婚禮腋逆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘百框。我一直安慰自己闲礼,他們只是感情好牍汹,可當(dāng)我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布铐维。 她就那樣靜靜地躺著,像睡著了一般慎菲。 火紅的嫁衣襯著肌膚如雪嫁蛇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天露该,我揣著相機(jī)與錄音睬棚,去河邊找鬼。 笑死解幼,一個胖子當(dāng)著我的面吹牛抑党,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撵摆,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼底靠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了特铝?” 一聲冷哼從身側(cè)響起暑中,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤壹瘟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鳄逾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稻轨,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年雕凹,在試婚紗的時候發(fā)現(xiàn)自己被綠了殴俱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡枚抵,死狀恐怖粱挡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情俄精,我是刑警寧澤询筏,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站竖慧,受9級特大地震影響嫌套,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜圾旨,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一踱讨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧砍的,春花似錦痹筛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至床佳,卻和暖如春滋早,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背砌们。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工杆麸, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浪感。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓昔头,卻偏偏與公主長得像,于是被迫代替她去往敵國和親影兽。 傳聞我的和親對象是個殘疾皇子揭斧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,901評論 2 355

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