1. 程式人生 > >Android Fragment使用小結及介紹

Android Fragment使用小結及介紹

偶記得第一次接觸Fragment,覺得好牛叉的元件,可以做許多Activity可以做的事,輔助Activity讓功能可以做得更加強大;一次編寫,可以多個地方可以使用,解放了Activity。在這裡,本篇文章主要是總結fragment的兩種新增方式,add和replace。

一、什麼是Fragment

簡單來說,Fragment其實可以理解為一個具有自己生命週期的控制元件,只不過這個控制元件又有點特殊,它有自己的處理輸入事件的能力,有自己的生命週期,又必須依賴於Activity,能互相通訊和託管。

使用Fragment還有這麼幾個方面優勢:

  • 程式碼複用。特別適用於模組化的開發,因為一個Fragment可以被多個Activity巢狀,有個共同的業務模組就可以複用了,是模組化UI的良好元件。
  • Activity用來管理Fragment。Fragment的生命週期是寄託到Activity中,Fragment可以被Attach新增和Detach釋放。
  • 可控性。Fragment可以像普通物件那樣自由的建立和控制,傳遞引數更加容易和方便,也不用處理系統相關的事情,顯示方式、替換、不管是整體還是部分,都可以做到相應的更改。
  • Fragments是view controllers,它們包含可測試的,解耦的業務邏輯塊,由於Fragments是構建在views之上的,而views很容易實現動畫效果,因此Fragments在螢幕切換時具有更好的控制。

二、Fragment的生命週期

Fragment的生命週期類似Activity,如下圖,Activity生命週期與Fragment生命週期對比圖:

這裡寫圖片描述

三、Fragment的兩種新增方式(add&replace)

Fragment新增與FragmentManager與FragmentTransaction息息相關。add和replace都是FragmentTransaction的方法。除這兩個方法,其中還有remove,hide和show方法。

FragmentManager與FragmentTransaction的獲取:

FragmentManager frgmentManager = getFragmentManager() // v4中,getSupportFragmentManager
FragmentTransaction transaction = frgmentManager.benginTransatcion();

1.專案中多個Fragment,add方式新增

i.新增程式碼

    public void add(BaseLibFragment fragment, int id,String tag){
        FragmentManager fragmentManager = ((BaseLibActivity)mContext).getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        //優先檢查,fragment是否存在,避免重疊
        BaseLibFragment tempFragment = (BaseLibFragment)fragmentManager.findFragmentByTag(tag);
        if(EmptyUtils.isNotEmpty(tempFragment)){
            fragment = tempFragment;
        }
        if(fragment.isAdded()){
            addOrShowFragment(fragmentTransaction,fragment,id,tag);
        }else{
            if(currentFragment!=null&&currentFragment.isAdded()){
                fragmentTransaction.hide(currentFragment).add(id, fragment,tag).commit();
            }else{
                fragmentTransaction.add(id, fragment,tag).commit();
            }
            currentFragment = fragment;
        }
    }
    /**
     * 新增或者顯示 fragment
     *
     * @param fragment
     */
    private void addOrShowFragment(FragmentTransaction transaction, BaseLibFragment fragment, int id,String tag) {
        if(currentFragment == fragment)
            return;
        if (!fragment.isAdded()) { // 如果當前fragment未被新增,則新增到Fragment管理器中
            transaction.hide(currentFragment).add(id, fragment,tag).commit();
        } else {
            transaction.hide(currentFragment).show(fragment).commit();
        }
        currentFragment.setUserVisibleHint(false);
        currentFragment =  fragment;
        currentFragment.setUserVisibleHint(true);
    }

ii.新增順序

  • 第一次新增,先hide(隱藏)currentFragment,再add(新增)新Fragment。生命週期會按正常流程走,onCreate->onResume
  • 第二次新增,先hide(隱藏)currentFragment,在show(顯示)老Fragment。生命週期不會重新走,會呼叫onHiddenChanged(),展示fragment的顯示狀態,我們可以在此做一些重新整理資料操作。

iii.add方式Fragment重疊BUG解決方案
為fragment設定Tag,通過findFragmentByTag查詢是否存在,然後再新增

//優先檢查,fragment是否存在,避免重疊
        BaseLibFragment tempFragment = (BaseLibFragment)fragmentManager.findFragmentByTag(tag);
        if(EmptyUtils.isNotEmpty(tempFragment)){
            fragment = tempFragment;
        }

2.專案中多個Fragment,replace方式新增
i.新增程式碼

    public void replace(BaseLibFragment fragment, int id){
        FragmentManager fragmentManager = ((BaseLibActivity)mContext).getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(id, fragment);
        fragmentTransaction.commit();
    }

ii.新增方式
新增方式比較直接,直接替換。在這過程中因為是替換,第一和第二次新增沒啥區別,生命週期都要重新執行一次

四、兩種新增方式效能比較

標準的四大金剛模式。底部四個Item,通過Fragment內容切換,此種方式add與replace效能對比,如下兩圖:

add方式

這裡寫圖片描述

replace方式
這裡寫圖片描述

由以上兩圖知:replace方式記憶體波動比較大,網路請求消耗大;add方式則反之。