Android Fragment使用(一) 基礎篇 溫故知新

Fragment使用基礎ide

Fragment添加模塊化

方法一: 佈局裏的標籤 標識符: tag, id, 若是都沒有, container的id將會被使用.函數

方法二: 動態添加 動態添加利用了一個transaction:佈局

FragmentManager fragmentManager = getFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag(FragmentB.TAG);
        if (null == fragment) {
            FragmentB fragmentB = new FragmentB();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.add(R.id.fragment_container, fragmentB, FragmentB.TAG)
                               .commit();
        }

commit()方法並不當即執行transaction中包含的動做,而是把它加入到UI線程隊列中. 若是想要當即執行,能夠在commit以後當即調用FragmentManager的executePendingTransactions()方法.線程

commit()方法必須在狀態存儲以前調用,不然會拋出異常,若是以爲狀態丟失不要緊,能夠調用commitAllowingStateLoss(). 可是除非萬不得已, 通常不推薦用這個方法, 會掩蓋不少錯誤.設計

Back Stackcode

Activity的back stack: 系統維護, 每一個task一個back stack. Fragment的back stack: 宿主activity掌管, 每一個activity一個.對象

經過調用addToBackStack(),commit()的一系列轉換做爲一個transaction被存儲在back stack中, 用戶按Back鍵, 從棧中pop出一個transaction, 逆轉操做, 能夠返回上一個轉換前的狀態.接口

一個transaction能夠包含多種操做, 而且不侷限於對同一個Fragment, 因此每個transaction實際上能夠是一系列對多個fragment的操做的組合. 加入到back stack中去的時候, 是把這一系列的組合做爲一個原子, 加入到back stack中.生命週期

構造和參數傳遞

全部的Fragment都必須有一個public的無參構造函數, 由於framework常常會在須要的時候從新建立實例(狀態恢復時), 它須要的就是這個構造. 若是無參構造沒有提供,會有異常.

因此不要給Fragment寫有參數的構造函數, 也不要企圖搞個什麼單例的Fragment. 這些都是反設計的.

參數傳遞的正確姿式:

public static FragmentWithParameters newInstance(int num) {
        FragmentWithParameters fragmentWithParameter = new FragmentWithParameters();
        Bundle args = new Bundle();
        args.putInt(NUM, num);
        fragmentWithParameter.setArguments(args);
        return fragmentWithParameter;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        num = getArguments() != null ? getArguments().getInt(NUM) : 0;
    }

這裏是提供了一個靜態方法, 也能夠new出對象後本身set Bundle參數.

Fragment的通訊 除了DialogFragment和嵌套Fragment須要與本身的parent fragment通訊之外, 通常的fragment是不與其餘fragment有任何通訊的. 由於要求應儘可能獨立, 模塊化, 可複用. fragment與本身的parent activity (除了嵌套和dialog的狀況外, 這個parent一般是activity) 有直接通訊, 通常以這三種方式:

在構造fragment的時候, 經過Bundle傳遞參數. parent能夠直接調用fragment的public方法, 這裏也能夠傳遞一些參數. Listener, 也即parent實現的callback接口, fragment能夠在本身內部調用, 這裏fragment也能夠傳遞參數出去. 對於DialogFragment來講, 能夠經過一個public的set方法將外面的target設置進去. 好比用Fragment的這個方法: setTargetFragment()

例子 對於嵌套(nested)Fragment, 通訊方式與上面普通的fragment相似, 只不過parent此時不是activity而是一個fragment. 後面會單獨有一個文章說嵌套Fragment的使用, 敬請期待.

Fragment的生命週期

Fragment的生命週期首先和Activity的生命週期密切相關, 若是activity stopped,其中全部的fragment都不能start; 若是activity destroyed, 其中全部的fragment都會被destroyed. 只有activity在resumed狀態下,fragment的生命週期能夠獨立改變,不然它被activity控制.

輸入圖片說明

輸入圖片說明

輸入圖片說明

輸入圖片說明

操做類型 FragmentTransaction 中對Fragment有以下幾種操做:

attach(), detach() add(), remove(), show(), hide(), replace() 除了replace()之外其餘都是成對的.

其中attach()和detach()不是很經常使用. 調用detach()以後, fragment實際的生命週期會走到onDestroyView(), 但不會走onDestroy()和onDetach(), 也即fragment自己並無被銷燬, 只是view被銷燬了. 這和addToBackStack()的狀況同樣, 儘管調用detach()的時候沒有addToBackStack(), 仍然只是走到view被銷燬的階段.

add()和remove()是將fragment添加和移除. remove()比detach()要完全一些, 若是不加入到back stack, remove()的時候, fragment的生命週期會一直走到onDetach().

show()和hide()是用來設置fragment的顯示和隱藏狀態, 這兩個方法並不對應fragment的狀態變化,只是將view設置爲visible和gone,而後調用onHiddenChanged()的回調.

實際上replace() == remove() + add(), 因此它的反操做也是replace(), 只不過把add和remove的東西交換一下.

關於replace()和show(), hide()的選擇, 要根據實際使用情形來定. replace()的好處是會減小內存佔用, 可是返回時須要從新走完初始化的過程. show()和hide()只是控制了fragment的顯示和隱藏, 不會改變生命週期狀態, 也即fragment始終是處於running狀態的, 被保持在內存中, 適用於頻繁切換的情形.

remove(), replace()是否加到back stack對生命週期的影響 前面說過, replace() == remove() + add() 新的fragment將取代在容器佈局中的fragment, 若是沒有,將直接添加新的fragment.

是否添加到back stack對fragment的生命週期是有影響的. remove()或者replace()的時候,若是commit()以前沒有調用addToBackStack(),那個舊fragment將會被destroyed和detach; 即徹底銷燬和移除.

若是調用了addToBackStack(),舊的fragment會處在stopped狀態,調用到onDestroyView(), 能夠經過返回鍵來resume. 這個時候對於舊的Fragment來講, 成員變量依然在,可是View被銷燬了. 因此返回時它的生命週期從onCreateView()開始重建View.

相關文章
相關標籤/搜索